Commit 75d62a05 authored by 4ast's avatar 4ast

Merge pull request #515 from vmg/vmg/static-lua

Lua tooling improvements
parents 330e4f2b 6b58ddf8
#!/usr/bin/env bcc-lua
--[[ --[[
Copyright 2016 GitHub, Inc Copyright 2016 GitHub, Inc
......
#!/usr/bin/env bcc-lua
--[[ --[[
Copyright 2016 GitHub, Inc Copyright 2016 GitHub, Inc
......
#!/usr/bin/env bcc-lua
--[[ --[[
Copyright 2016 GitHub, Inc Copyright 2016 GitHub, Inc
......
#!/usr/bin/env bcc-lua
--[[ --[[
Copyright 2016 GitHub, Inc Copyright 2016 GitHub, Inc
......
#!/usr/bin/env bcc-lua
--[[ --[[
Copyright 2016 GitHub, Inc Copyright 2016 GitHub, Inc
......
...@@ -2,7 +2,9 @@ find_package(LuaJIT) ...@@ -2,7 +2,9 @@ find_package(LuaJIT)
find_program(LUAJIT luajit) find_program(LUAJIT luajit)
if (LUAJIT_LIBRARIES AND LUAJIT) if (LUAJIT_LIBRARIES AND LUAJIT)
FILE(GLOB_RECURSE SRC_LUA ${CMAKE_CURRENT_SOURCE_DIR}/bcc/*/*.lua) FILE(GLOB_RECURSE SRC_LUA
${CMAKE_CURRENT_SOURCE_DIR}/bcc/*.lua
${CMAKE_CURRENT_SOURCE_DIR}/bcc/vendor/*.lua)
ADD_CUSTOM_COMMAND( ADD_CUSTOM_COMMAND(
OUTPUT bcc.lua OUTPUT bcc.lua
...@@ -18,7 +20,9 @@ if (LUAJIT_LIBRARIES AND LUAJIT) ...@@ -18,7 +20,9 @@ if (LUAJIT_LIBRARIES AND LUAJIT)
include_directories(${LUAJIT_INCLUDE_DIR}) include_directories(${LUAJIT_INCLUDE_DIR})
add_executable(bcc-lua src/main.c bcc.o) add_executable(bcc-lua src/main.c bcc.o)
set_target_properties(bcc-lua PROPERTIES LINKER_LANGUAGE C)
target_link_libraries(bcc-lua ${LUAJIT_LIBRARIES}) target_link_libraries(bcc-lua ${LUAJIT_LIBRARIES})
target_link_libraries(bcc-lua -Wl,--whole-archive bcc-static -Wl,--no-whole-archive)
install(TARGETS bcc-lua RUNTIME DESTINATION bin) install(TARGETS bcc-lua RUNTIME DESTINATION bin)
endif() endif()
...@@ -17,5 +17,4 @@ limitations under the License. ...@@ -17,5 +17,4 @@ limitations under the License.
local str = require("debug").getinfo(1, "S").source:sub(2) local str = require("debug").getinfo(1, "S").source:sub(2)
local script_path = str:match("(.*/)").."/?.lua;" local script_path = str:match("(.*/)").."/?.lua;"
package.path = script_path..package.path package.path = script_path..package.path
rawset(_G, "BCC_STANDALONE_NAME", "bcc-probe")
require("bcc.run")() require("bcc.run")()
...@@ -41,7 +41,8 @@ function Bpf.static.cleanup_probes() ...@@ -41,7 +41,8 @@ function Bpf.static.cleanup_probes()
local function detach_all(probe_type, all_probes) local function detach_all(probe_type, all_probes)
for key, probe in pairs(all_probes) do for key, probe in pairs(all_probes) do
libbcc.perf_reader_free(probe) libbcc.perf_reader_free(probe)
if type(key) == "string" then -- skip bcc-specific kprobes
if not key:starts("bcc:") then
local desc = string.format("-:%s/%s", probe_type, key) local desc = string.format("-:%s/%s", probe_type, key)
log.info("detaching %s", desc) log.info("detaching %s", desc)
......
...@@ -112,4 +112,11 @@ int bcc_symcache_resolve(void *symcache, uint64_t addr, struct bcc_symbol *sym); ...@@ -112,4 +112,11 @@ int bcc_symcache_resolve(void *symcache, uint64_t addr, struct bcc_symbol *sym);
void bcc_symcache_refresh(void *resolver); void bcc_symcache_refresh(void *resolver);
]] ]]
return ffi.load(os.getenv("LIBBCC_SO_PATH") or rawget(_G, "LIBBCC_SO_PATH") or "bcc") if rawget(_G, "BCC_STANDALONE") then
return ffi.C
else
return ffi.load(
os.getenv("LIBBCC_SO_PATH") or
rawget(_G, "LIBBCC_SO_PATH") or
"bcc")
end
...@@ -16,11 +16,12 @@ limitations under the License. ...@@ -16,11 +16,12 @@ limitations under the License.
return function() return function()
require("bcc.vendor.helpers") require("bcc.vendor.helpers")
local progname = rawget(_G, "BCC_STANDALONE_NAME") or "bcc-lua" local standalone = rawget(_G, "BCC_STANDALONE")
local progname = standalone or "bcc-probe"
local function print_usage() local function print_usage()
io.stderr:write(string.format( io.stderr:write(string.format(
"usage: %s [[--so-path=PATH|--version|--verbose] --] path_to_script.lua [...]\n", "usage: %s [[--version|--verbose] --] path_to_script.lua [...]\n",
progname)) progname))
os.exit(1) os.exit(1)
end end
...@@ -37,7 +38,7 @@ return function() ...@@ -37,7 +38,7 @@ return function()
local k = table.remove(arg, 1) local k = table.remove(arg, 1)
if k == "--" then if k == "--" then
break break
elseif string.starts(k, "--so-path=") then elseif standalone == nil and string.starts(k, "--so-path=") then
rawset(_G, "LIBBCC_SO_PATH", string.lstrip(k, "--so-path=")) rawset(_G, "LIBBCC_SO_PATH", string.lstrip(k, "--so-path="))
elseif k == "--llvm-debug" then elseif k == "--llvm-debug" then
rawset(_G, "LIBBCC_LLVM_DEBUG", 1) rawset(_G, "LIBBCC_LLVM_DEBUG", 1)
......
...@@ -236,7 +236,7 @@ function PerfEventArray:initialize(bpf, map_id, map_fd, key_type, leaf_type) ...@@ -236,7 +236,7 @@ function PerfEventArray:initialize(bpf, map_id, map_fd, key_type, leaf_type)
end end
local function _perf_id(id, cpu) local function _perf_id(id, cpu)
return string.format("perf_event_array:%d:%d", tonumber(id), cpu or 0) return string.format("bcc:perf_event_array:%d:%d", tonumber(id), cpu or 0)
end end
function PerfEventArray:_open_perf_buffer(cpu, callback, ctype) function PerfEventArray:_open_perf_buffer(cpu, callback, ctype)
......
...@@ -29,166 +29,142 @@ ...@@ -29,166 +29,142 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include "lua.h"
#include "lauxlib.h" #include "lauxlib.h"
#include "lua.h"
#include "lualib.h" #include "lualib.h"
static lua_State *globalL = NULL; static lua_State *globalL = NULL;
static const char *progname = NULL; static const char *progname = NULL;
static void lstop(lua_State *L, lua_Debug *ar) static void lstop(lua_State *L, lua_Debug *ar) {
{ (void)ar; /* unused arg. */
(void)ar; /* unused arg. */ lua_sethook(L, NULL, 0, 0);
lua_sethook(L, NULL, 0, 0); luaL_error(L, "interrupted!");
luaL_error(L, "interrupted!");
} }
static void laction(int i) static void laction(int i) {
{ signal(i, SIG_DFL);
signal(i, SIG_DFL); lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);
} }
static void l_message(const char *pname, const char *msg) static void l_message(const char *pname, const char *msg) {
{ if (pname)
if (pname) fprintf(stderr, "%s: ", pname); fprintf(stderr, "%s: ", pname);
fprintf(stderr, "%s\n", msg); fprintf(stderr, "%s\n", msg);
fflush(stderr); fflush(stderr);
} }
static int report(lua_State *L, int status) static int report(lua_State *L, int status) {
{ if (status && !lua_isnil(L, -1)) {
if (status && !lua_isnil(L, -1)) { const char *msg = lua_tostring(L, -1);
const char *msg = lua_tostring(L, -1); if (msg == NULL)
if (msg == NULL) msg = "(error object is not a string)"; msg = "(error object is not a string)";
l_message(progname, msg); l_message(progname, msg);
lua_pop(L, 1); lua_pop(L, 1);
} }
return status; return status;
} }
static int traceback(lua_State *L) static int traceback(lua_State *L) {
{ if (!lua_isstring(L, 1)) /* 'message' not a string? */
if (!lua_isstring(L, 1)) /* 'message' not a string? */ return 1; /* keep it intact */
return 1; /* keep it intact */ lua_getfield(L, LUA_GLOBALSINDEX, "debug");
lua_getfield(L, LUA_GLOBALSINDEX, "debug"); if (!lua_istable(L, -1)) {
if (!lua_istable(L, -1)) { lua_pop(L, 1);
lua_pop(L, 1); return 1;
return 1; }
} lua_getfield(L, -1, "traceback");
lua_getfield(L, -1, "traceback"); if (!lua_isfunction(L, -1)) {
if (!lua_isfunction(L, -1)) { lua_pop(L, 2);
lua_pop(L, 2); return 1;
return 1; }
} lua_pushvalue(L, 1); /* pass error message */
lua_pushvalue(L, 1); /* pass error message */ lua_pushinteger(L, 2); /* skip this function and traceback */
lua_pushinteger(L, 2); /* skip this function and traceback */ lua_call(L, 2, 1); /* call debug.traceback */
lua_call(L, 2, 1); /* call debug.traceback */ return 1;
return 1;
} }
static int docall(lua_State *L, int narg, int clear) static int docall(lua_State *L, int narg, int clear) {
{ int status;
int status; int base = lua_gettop(L) - narg; /* function index */
int base = lua_gettop(L) - narg; /* function index */ lua_pushcfunction(L, traceback); /* push traceback function */
lua_pushcfunction(L, traceback); /* push traceback function */ lua_insert(L, base); /* put it under chunk and args */
lua_insert(L, base); /* put it under chunk and args */ signal(SIGINT, laction);
signal(SIGINT, laction); status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base);
status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base); signal(SIGINT, SIG_DFL);
signal(SIGINT, SIG_DFL); lua_remove(L, base); /* remove traceback function */
lua_remove(L, base); /* remove traceback function */ /* force a complete garbage collection in case of errors */
/* force a complete garbage collection in case of errors */ if (status != 0)
if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0); lua_gc(L, LUA_GCCOLLECT, 0);
return status; return status;
} }
static int dolibrary(lua_State *L, const char *name, int clear) static int dolibrary(lua_State *L, const char *name, int clear) {
{ lua_getglobal(L, "require");
lua_getglobal(L, "require"); lua_pushstring(L, name);
lua_pushstring(L, name); return report(L, docall(L, 1, clear));
return report(L, docall(L, 1, clear));
} }
struct Smain { struct Smain {
int argc; int argc;
char **argv; char **argv;
int status; int status;
}; };
static void pushargv(lua_State *L, char **argv, int argc, int offset) static void pushargv(lua_State *L, char **argv, int argc, int offset) {
{ int i, j;
int i, j; lua_createtable(L, argc, 0);
lua_createtable(L, argc, 0); for (i = offset, j = 1; i < argc; i++, j++) {
for (i = offset, j = 1; i < argc; i++, j++) { lua_pushstring(L, argv[i]);
lua_pushstring(L, argv[i]); lua_rawseti(L, -2, j);
lua_rawseti(L, -2, j); }
}
} }
static void find_local_libbcc(lua_State *L) static int pmain(lua_State *L) {
{ struct Smain *s = (struct Smain *)lua_touserdata(L, 1);
char buffer[4096]; globalL = L;
char *dirname;
if (readlink("/proc/self/exe", buffer, sizeof(buffer)) < 0) lua_gc(L, LUA_GCSTOP, 0);
return; luaL_openlibs(L);
lua_gc(L, LUA_GCRESTART, 0);
dirname = strrchr(buffer, '/'); s->status = dolibrary(L, "bcc", 0);
if (dirname == NULL) if (s->status)
return; return 0;
strcpy(dirname + 1, "libbcc.so"); lua_pushstring(L, progname);
lua_setglobal(L, "BCC_STANDALONE");
if (access(buffer, F_OK|R_OK|X_OK) != 0) pushargv(L, s->argv, s->argc, 1);
return; lua_setglobal(L, "arg");
lua_pushstring(L, buffer); s->status = report(L, docall(L, 0, 1));
lua_setglobal(L, "LIBBCC_SO_PATH"); return 0;
} }
static int pmain(lua_State *L) int main(int argc, char **argv) {
{ int status;
struct Smain *s = (struct Smain *)lua_touserdata(L, 1); struct Smain s;
globalL = L; lua_State *L = lua_open(); /* create state */
lua_gc(L, LUA_GCSTOP, 0);
luaL_openlibs(L);
lua_gc(L, LUA_GCRESTART, 0);
find_local_libbcc(L);
s->status = dolibrary(L, "bcc", 0);
if (s->status)
return 0;
lua_pushstring(L, progname);
lua_setglobal(L, "BCC_STANDALONE_NAME");
pushargv(L, s->argv, s->argc, 1);
lua_setglobal(L, "arg");
s->status = report(L, docall(L, 0, 1));
return 0;
}
int main(int argc, char **argv) if (L == NULL) {
{ l_message(argv[0], "cannot create state: not enough memory");
int status; return EXIT_FAILURE;
struct Smain s; }
lua_State *L = lua_open(); /* create state */
if (L == NULL) { if (geteuid() != 0) {
l_message(argv[0], "cannot create state: not enough memory"); l_message(argv[0], "bcc-lua must be ran as root");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
progname = argv[0]; progname = argv[0];
s.argc = argc; s.argc = argc;
s.argv = argv; s.argv = argv;
s.status = 0; s.status = 0;
status = lua_cpcall(L, &pmain, &s); status = lua_cpcall(L, &pmain, &s);
report(L, status); report(L, status);
lua_close(L); lua_close(L);
return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS; return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS;
} }
...@@ -372,7 +372,7 @@ class PerfEventArray(ArrayBase): ...@@ -372,7 +372,7 @@ class PerfEventArray(ArrayBase):
super(PerfEventArray, self).__init__(*args, **kwargs) super(PerfEventArray, self).__init__(*args, **kwargs)
def __delitem__(self, key): def __delitem__(self, key):
super(PerfEventArray, self).__init__(key) super(PerfEventArray, self).__delitem__(key)
self.close_perf_buffer(key) self.close_perf_buffer(key)
def open_perf_buffer(self, callback): def open_perf_buffer(self, callback):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment