forked from LuaJIT/LuaJIT
-
Notifications
You must be signed in to change notification settings - Fork 13
/
lj-549-bytecode-loader.test.lua
97 lines (82 loc) · 2.88 KB
/
lj-549-bytecode-loader.test.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
local tap = require('tap')
local test = tap.test('lj-549-bytecode-loader')
local ffi = require('ffi')
local exec = require('utils').exec
test:plan(1)
-- Test creates a shared library with LuaJIT bytecode,
-- loads shared library as a Lua module and checks,
-- that no crashes eliminated.
--
-- $ make HOST_CC='gcc -m32' TARGET_CFLAGS='-m32' \
-- TARGET_LDFLAGS='-m32' \
-- TARGET_SHLDFLAGS='-m32' \
-- -f Makefile.original
-- $ echo 'print("test")' > a.lua
-- $ LUA_PATH="src/?.lua;;" luajit -b a.lua a.c
-- $ gcc -m32 -fPIC -shared a.c -o a.so
-- $ luajit -e "require('a')"
-- Program received signal SIGBUS, Bus error
local function file_exists(fname)
local fh = io.open(fname, 'r')
return fh and io.close(fh)
end
local function basedir(path)
return path:match('(.*[/\\])') or './'
end
local function basename(path)
return path:match("[^/]*$")
end
-- Create a C file with LuaJIT bytecode.
-- We cannot use utils.makecmd, because command-line generated
-- by `makecmd` contains `-e` that is incompatible with option
-- `-b`.
local function create_c_file(pathlua, pathc)
local lua_path = os.getenv('LUA_PATH')
local lua_bin = exec.luacmd(arg):match('%S+')
local cmd_fmt = 'LUA_PATH="%s" %s -b %s %s'
local cmd = (cmd_fmt):format(lua_path, lua_bin, pathlua, pathc)
local ret = os.execute(cmd)
assert(ret == 0, 'create a C file with bytecode')
end
local stdout_msg = 'Lango team'
local lua_code = ('print(%q)'):format(stdout_msg)
local fpath = os.tmpname()
local path_lua = ('%s.lua'):format(fpath)
local path_c = ('%s.c'):format(fpath)
local path_so = ('%s.so'):format(fpath)
-- Create a file with a minimal Lua code.
local fh = assert(io.open(path_lua, 'w'))
fh:write(lua_code)
fh:close()
local module_name = assert(basename(fpath))
create_c_file(path_lua, path_c)
assert(file_exists(path_c))
-- Compile C source code with LuaJIT bytecode to a shared library.
-- `-m64` is not available on ARM64, see
-- "3.18.1 AArch64 Options in the manual",
-- https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html.
local cflags_64 = jit.arch == 'arm64' and '-march=armv8-a' or '-m64'
local cflags = ffi.abi('32bit') and '-m32' or cflags_64
local cc_cmd = ('cc %s -fPIC -shared %s -o %s'):format(cflags, path_c, path_so)
local rc = os.execute(cc_cmd)
assert(rc == 0)
assert(file_exists(path_so))
-- Load shared library as a Lua module.
local lua_cpath = ('"/tmp/?.so;"'):format(basedir(fpath))
assert(file_exists(path_so))
local cmd = exec.makecmd(arg, {
script = ('-e "require([[%s]])"'):format(module_name),
env = {
LUA_CPATH = lua_cpath,
-- It is required to cleanup LUA_PATH, otherwise
-- LuaJIT loads Lua module, see
-- tarantool-tests/utils/init.lua.
LUA_PATH = '',
},
})
local res = cmd()
test:ok(res == stdout_msg, 'bytecode loader works')
os.remove(path_lua)
os.remove(path_c)
os.remove(path_so)
test:done(true)