Lua: compiling C module gives "multiple Lua VMs detected" - c

I am using Lua 5.3.4 on Mac OS X 10.12 (Sierra).
I have build Lua using "make macosx install".
I am trying to extend Lua, writing a C module that I can call from Lua.
To do that I wrote this C code:
#include <math.h>
#include <lua/lua.h>
#include <lua/lauxlib.h>
#include <lua/lualib.h>
static int l_sin (lua_State *L)
{
double d = lua_tonumber (L, 1);
lua_pushnumber (L, sin (d));
return 1;
}
static const struct luaL_Reg mylib[] = {
{"l_sin", l_sin},
{NULL, NULL}
};
int luaopen_mylib (lua_State *L)
{
luaL_newlib (L, mylib);
return 1;
}
If I try to compile it with gcc -Wall -shared -fPIC -o mylib.so -llua mylib.c (or in every other way I found online), when I do l = require "mylib" on the Lua interpreter, I get multiple Lua VMs detected. (of course I have copied the shared library in the right path)
I can't find a solution, can you help me? Thanks

Related

Trying to write a Lua module in C on Arch Linux will segfault

I wrote the following C file (for lua 5.1) bar_src.c:
#include <lua5.1/lua.h>
#include <lua5.1/lauxlib.h>
#include <lua5.1/lualib.h>
static int foo(lua_State *L)
{
int a = luaL_checknumber(L, 1);
int b = luaL_checknumber(L, 2);
lua_pushnumber(L, a + b);
return 1;
}
luaL_Reg foolib[] = {
{"foo", foo},
{NULL, NULL}
};
int luaopen_bar(lua_State *L)
{
luaL_register(L, "bar", foolib);
return 1;
}
And compiled it with: gcc -shared -fpic -o bar.so bar.c -llua5.1.
However, whenever I try running require("bar") in lua, it instantly does segmentation fault (core dumped).
I wanted to try on another system, so I did the same thing on repl.it (which runs on Ubuntu 18.04) and everything worked perfectly, meaning my Linux configuration has an issue.
Edit:
I found the core dump for the segfault in /var/lib/systemd/coredump, and loaded it into GDB with gdb $(which lua) /var/lib/systemd/coredump/core.lua.[file], and gdb said:
Core was generated by `lua'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x00005620820f3ad3 in lua_pushvalue ()
The problem was that I was using the lua 5.4 interpreter, I should have run it with the lua5 .1 command.
In this example, I used the older version of Lua, Lua 5.1, but the arch package of Lua has 5.1, 5.2, 5.3, and the latest 5.4 installed. Although there isn't much documentation for 5.4, there is a reference manual. The compiler said that the function luaL_register was not in Lua 5.4, but I found a replacement called luaL_newlib() in the manual.
I changed my code to look like this:
#include <lua5.1/lua.h>
#include <lua5.1/lauxlib.h>
#include <lua5.1/lualib.h>
static int foo(lua_State *L)
{
int a = luaL_checknumber(L, 1);
int b = luaL_checknumber(L, 2);
lua_pushnumber(L, a + b);
return 1;
}
luaL_Reg foolib[] = {
{"foo", foo},
{NULL, NULL}
};
int luaopen_bar(lua_State *L)
{
luaL_newlib(L, foolib);
return 1;
}
This code compiled perfectly amd when I required it, there were no segfaults.

How call and compile function from elf to my binary?

I have a binary file (ELF) that I don't write, but I want to use 1 function from this binary (I know the address/offset of the function), that function not exported from the binary.
My goal is to call this function from my C code that I write and compile this function statically in my binary (I compile with gcc).
How can I do that please?
I am going to answer the
call to this function from my c code that I write
part.
The below works under certain assumptions, like dynamic linking and position independent code. I haven't thought for too long about what happens if they are broken (let's experiment/discuss, if there's interest).
$ cat lib.c
int data = 42;
static int foo () { return data; }
gcc -fpic -shared lib.c -o lib.so
$ nm lib.so | grep foo
00000000000010e9 t foo
The above reproduces having the address that you know. The address we know now is 0x10e9. It is the virtual address of foo before relocation. We'll model the relocation the dynamic loader does by hand by simply adding the base address at which lib.so gets loaded.
$ cat 1.c
#define _GNU_SOURCE
#include <stdio.h>
#include <link.h>
#include <string.h>
#include <elf.h>
#define FOO_VADDR 0x10e9
typedef int(*func_t)();
int callback(struct dl_phdr_info *info, size_t size, void *data)
{
if (!(strstr(info->dlpi_name, "lib.so")))
return 0;
Elf64_Addr addr = info->dlpi_addr + FOO_VADDR;
func_t f = (func_t)addr;
int res = f();
printf("res = %d\n", res);
return 0;
}
int main()
{
void *handle = dlopen("./lib.so", RTLD_LAZY);
if (!handle) {
puts("failed to load");
return 1;
}
dl_iterate_phdr(&callback, NULL);
dlclose(handle);
return 0;
}
And now...
$ gcc 1.c -ldl && ./a.out
res = 42
Voila -- it worked! That was fun.
Credit: this was helpful.
If you have questions, feel free to read the man and ask in the comments.
As for
compile this function statically in my binary
I don't know off the bat. This would be trickier. Why do you want that? Also, do you know whether the function depends on some data (or maybe it calls other functions) in the original ELF file, like in the example above?

shared libraries and visibility to user's memory

When I use a shared library via dlopen, can the library code "see" memory of my process that calls dlopen? For example, I would like to pass a pointer to memory allocated by my application to the library API.
I'm on Linux/x86 if it is important.
The answer is yes, it can. Here is a simple quick example for illustration purposes.
The library code (in file myso.c):
void setInt( int * i )
{
*i = 12345;
}
The library can be built as follows:
gcc -c -fPIC myso.c
gcc -shared -Wl,-soname,libmy.so -o libmy.so myso.o -lc
Here is the client code (main.c):
#include <stdio.h>
#include <dlfcn.h>
typedef void (*setint_t)( int * );
int main()
{
void * h = dlopen("./libmy.so", RTLD_NOW);
if (h)
{
puts("Loaded library.");
setint_t setInt = dlsym( h, "setInt" );
if (setInt) {
puts("Symbol found");
int k;
setInt(&k);
printf("The int is %d\n", k);
}
}
return 0;
}
Now build and run the code. Make sure main.c and the library are in the same directory, in which we execute the following:
user#fedora-21 ~]$ gcc main.c -ldl
[user#fedora-21 ~]$ ./a.out
Loaded library.
Symbol found
The int is 12345
As one can see, the library was able to write to the memory of the integer k.

gcc shared library with header in the same library

I'm trying to compile a shared library (.so) with the following code:
libreceive.h:
#include <stddef.h>
int receive(int sockfd, void *buf, size_t len, int flags);
libreceive.c
#include <stddef.h>
#include <libreceive/libreceive.h>
int receive(int sockfd, void *buf, size_t len, int flags){
return recv(sockfd, buf, len, flags);
}
the problem here is that I'm trying to include the .h in the library that I'm building and using it in the same time from the same library in the .c .
I know that what I'm trying to do is possible, but I can't manage to do it.
How can I do that please.
the code I'm trying is:
gcc -o libreceive.o -c -include libreceive.h libreceive.c
I get the following error:
fatal error: libreceive/libreceive.h: No such file or directory
compilation terminated.
the problem here is that I'm trying to include the .h in the library that I'm building and using it in the same time from the same library in the .c .
I know that what I'm trying to do is possible, but I can't manage to do it.
How can I do that please.
Since libreceive.h and libreceive.c appear to be in the same directory (judging from your compiler call), the normal way is
#include "libreceive.h"
In order to use
#include <libreceive/libreceive.h>
libreceive.h would have to lie in a directory called libreceive, and that directory would have to be part of the include path. It is possible to achieve this, but I believe it is neither necessary nor useful here.
You are missing out a few steps here.
Consider the following setup.
File: add.c
#include "header.h"
int add(int a, int b)
{
printf("SIZE: %d\n", SIZE);
return a+b;
}
File: sub.c
#include "header.h"
int sub(int a, int b)
{
printf("SIZE: %d\n", SIZE);
return a-b;
}
File: header.h, located in directory called include.
#include <stdio.h>
#define SIZE 100
int add(int a, int b);
int sub(int a, int b);
So to step by step build a .so file.
/* Build `.o` files first */
$ gcc -fPIC -c sub.c -I path/to/include/
$ gcc -fPIC -c add.c -I path/to/include/
/* Build shared library called libsample.so */
$ gcc -shared -o libsample.so add.o sub.o
The above command will build a .so by name libsample.so.
Where all definition from .c(like functions) and .h(like #defines) will get included in your library.
How to use this in your code:
Consider the file
File: main.c
#include <stdio.h>
int main()
{
int a = 3, b = 4;
printf("Return : %d\n", add(a, b));
return 0;
}
To make use of your library libsample.so.
$ export LD_LIBRARY_PATH=/path/to/direc/containing/.so/file
$ gcc -o exe main.c -lsample -L/path/to/direc/containing/.so/file
The above command should create a binary called exe.
$./exe
SIZE : 100 /* SIZE Defined in .h file */
Return : 7 /* Defined in add.c */
You can refer this guide : http://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html
Finaly I decided to use #include "libreceive.h" as suggested by the guys. the probleme I had is that the compiler was looking for my so in /usr/lib wich is the default when id do sudo gcc and my usr had the $LD_LIBRARY_PATH at /usr/local/lib and therefore gcc coudn't find my library at compile time
another problem was that the program that call thos .so was looking fro the .h in some folder that doesn't exist and I had to add it.
thanks guys for you answers

Running luajit object file from C

From the documentation: http://luajit.org/running.html
luajit -b test.lua test.obj # Generate object file
# Link test.obj with your application and load it with require("test")
But doesn't explain how to do these things. I guess they're assuming anyone using Lua is also a C programmer, not the case with me! Can I get some help? GCC as an example.
I would also like to do the same thing except from the C byte array header. I can't find documentation on this either.
luajit -bt h -n test test.lua test.h
This creates the header file but I don't know how to run it from C. Thanks.
main.lua
print("Hello from main.lua")
app.c
#include <stdio.h>
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
int main(int argc, char **argv)
{
int status;
lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_getglobal(L, "require");
lua_pushliteral(L, "main");
status = lua_pcall(L, 1, 0, 0);
if (status) {
fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
return 1;
}
return 0;
}
Shell commands:
luajit -b main.lua main.o
gcc -O2 -Wall -Wl,-E -o app app.c main.o -Ixx -Lxx -lluajit-5.1 -lm -ldl
Replace -Ixx and -Lxx by the LuaJIT include and library directories. If you've installed it in /usr/local (the default), then most GCC installations will find it without these two options.
The first command compiles the Lua source code to bytecode and embeds it into the object file main.o.
The second command compiles and links the minimal C application code. Note that it links in the embedded bytecode, too. The -Wl,-E is mandatory (on Linux) to export all symbols from the executable.
Now move the original main.lua away (to ensure it's really running the embedded bytecode and not the Lua source code file) and then run your app:
mv main.lua main.lua.orig
./app
# Output: Hello from main.lua
The basic usage is as follows:
Generate the header file using luajit
#include that header in the source file(s) that's going to be referencing its symbols
Compile the source into a runnable executable or shared binary module for lua depending on your use-case.
Here's a minimal example to illustrate:
test.lua
return
{
fooprint = function (s) return print("from foo: "..s) end,
barprint = function (s) return print("from bar: "..s) end
}
test.h
// luajit -b test.lua test.h
#define luaJIT_BC_test_SIZE 155
static const char luaJIT_BC_test[] = {
27,76,74,1,2,44,0,1,4,0,2,0,5,52,1,0,0,37,2,1,0,16,3,0,0,36,2,3,2,64,1,2,0,15,
102,114,111,109,32,102,111,111,58,32,10,112,114,105,110,116,44,0,1,4,0,2,0,5,
52,1,0,0,37,2,1,0,16,3,0,0,36,2,3,2,64,1,2,0,15,102,114,111,109,32,98,97,114,
58,32,10,112,114,105,110,116,58,3,0,2,0,5,0,7,51,0,1,0,49,1,0,0,58,1,2,0,49,1,
3,0,58,1,4,0,48,0,0,128,72,0,2,0,13,98,97,114,112,114,105,110,116,0,13,102,
111,111,112,114,105,110,116,1,0,0,0,0
};
runtest.cpp
// g++ -Wall -pedantic -g runtest.cpp -o runtest.exe -llua51
#include <stdio.h>
#include <assert.h>
#include "lua.hpp"
#include "test.h"
static const char *runtest =
"test = require 'test'\n"
"test.fooprint('it works!')\n"
"test.barprint('it works!')\n";
int main()
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_getglobal(L, "package");
lua_getfield(L, -1, "preload");
// package, preload, luaJIT_BC_test
bool err = luaL_loadbuffer(L, luaJIT_BC_test, luaJIT_BC_test_SIZE, NULL);
assert(!err);
// package.preload.test = luaJIT_BC_test
lua_setfield(L, -2, "test");
// check that 'test' lib is now available; run the embedded test script
lua_settop(L, 0);
err = luaL_dostring(L, runtest);
assert(!err);
lua_close(L);
}
This is pretty straight-forward. This example takes the byte-code and places it into the package.preload table for this program's lua environment. Other lua scripts can then use this by doing require 'test'. The embedded lua source in runtest does exactly this and outputs:
from foo: it works!
from bar: it works!

Resources