siger-young updated this revision to Diff 375081.
siger-young added a comment.
This update mainly fixed problematic typemaps and adding necessary comments.
Together, it forced Lua installation path as "PREFIX/lib/lua/5.3" and removed
"lit.util" in tests.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D108090/new/
https://reviews.llvm.org/D108090
Files:
lldb/CMakeLists.txt
lldb/bindings/lua/CMakeLists.txt
lldb/bindings/lua/lua-typemaps.swig
lldb/test/API/lua_api/TestComprehensive.lua
lldb/test/API/lua_api/TestLuaAPI.py
Index: lldb/test/API/lua_api/TestLuaAPI.py
===================================================================
--- lldb/test/API/lua_api/TestLuaAPI.py
+++ lldb/test/API/lua_api/TestLuaAPI.py
@@ -5,8 +5,129 @@
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
-import lit.util
+import subprocess
+def to_string(b):
+ """Return the parameter as type 'str', possibly encoding it.
+
+ In Python2, the 'str' type is the same as 'bytes'. In Python3, the
+ 'str' type is (essentially) Python2's 'unicode' type, and 'bytes' is
+ distinct.
+
+ """
+ if isinstance(b, str):
+ # In Python2, this branch is taken for types 'str' and 'bytes'.
+ # In Python3, this branch is taken only for 'str'.
+ return b
+ if isinstance(b, bytes):
+ # In Python2, this branch is never taken ('bytes' is handled as 'str').
+ # In Python3, this is true only for 'bytes'.
+ try:
+ return b.decode('utf-8')
+ except UnicodeDecodeError:
+ # If the value is not valid Unicode, return the default
+ # repr-line encoding.
+ return str(b)
+
+ # By this point, here's what we *don't* have:
+ #
+ # - In Python2:
+ # - 'str' or 'bytes' (1st branch above)
+ # - In Python3:
+ # - 'str' (1st branch above)
+ # - 'bytes' (2nd branch above)
+ #
+ # The last type we might expect is the Python2 'unicode' type. There is no
+ # 'unicode' type in Python3 (all the Python3 cases were already handled). In
+ # order to get a 'str' object, we need to encode the 'unicode' object.
+ try:
+ return b.encode('utf-8')
+ except AttributeError:
+ raise TypeError('not sure how to convert %s to %s' % (type(b), str))
+
+class ExecuteCommandTimeoutException(Exception):
+ def __init__(self, msg, out, err, exitCode):
+ assert isinstance(msg, str)
+ assert isinstance(out, str)
+ assert isinstance(err, str)
+ assert isinstance(exitCode, int)
+ self.msg = msg
+ self.out = out
+ self.err = err
+ self.exitCode = exitCode
+
+
+# Close extra file handles on UNIX (on Windows this cannot be done while
+# also redirecting input).
+kUseCloseFDs = not (platform.system() == 'Windows')
+
+
+def executeCommand(command, cwd=None, env=None, input=None, timeout=0):
+ """Execute command ``command`` (list of arguments or string) with.
+
+ * working directory ``cwd`` (str), use None to use the current
+ working directory
+ * environment ``env`` (dict), use None for none
+ * Input to the command ``input`` (str), use string to pass
+ no input.
+ * Max execution time ``timeout`` (int) seconds. Use 0 for no timeout.
+
+ Returns a tuple (out, err, exitCode) where
+ * ``out`` (str) is the standard output of running the command
+ * ``err`` (str) is the standard error of running the command
+ * ``exitCode`` (int) is the exitCode of running the command
+
+ If the timeout is hit an ``ExecuteCommandTimeoutException``
+ is raised.
+
+ """
+ if input is not None:
+ input = to_bytes(input)
+ p = subprocess.Popen(command, cwd=cwd,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ env=env, close_fds=kUseCloseFDs)
+ timerObject = None
+ # FIXME: Because of the way nested function scopes work in Python 2.x we
+ # need to use a reference to a mutable object rather than a plain
+ # bool. In Python 3 we could use the "nonlocal" keyword but we need
+ # to support Python 2 as well.
+ hitTimeOut = [False]
+ try:
+ if timeout > 0:
+ def killProcess():
+ # We may be invoking a shell so we need to kill the
+ # process and all its children.
+ hitTimeOut[0] = True
+ killProcessAndChildren(p.pid)
+
+ timerObject = threading.Timer(timeout, killProcess)
+ timerObject.start()
+
+ out, err = p.communicate(input=input)
+ exitCode = p.wait()
+ finally:
+ if timerObject != None:
+ timerObject.cancel()
+
+ # Ensure the resulting output is always of string type.
+ out = to_string(out)
+ err = to_string(err)
+
+ if hitTimeOut[0]:
+ raise ExecuteCommandTimeoutException(
+ msg='Reached timeout of {} seconds'.format(timeout),
+ out=out,
+ err=err,
+ exitCode=exitCode
+ )
+
+ # Detect Ctrl-C in subprocess.
+ if exitCode == -signal.SIGINT:
+ raise KeyboardInterrupt
+
+ return out, err, exitCode
class TestLuaAPI(TestBase):
@@ -41,7 +162,7 @@
test_output = self.getBuildArtifact("output")
test_input = self.getBuildArtifact("input")
- lua_lldb_cpath = "%s/lua/?.so" % configuration.lldb_libs_dir
+ lua_lldb_cpath = "%s/lua/5.3/?.so" % configuration.lldb_libs_dir
lua_prelude = "package.cpath = '%s;' .. package.cpath" % lua_lldb_cpath
@@ -53,7 +174,7 @@
for lua_test in self.get_tests():
cmd = [lua_executable] + ["-e", lua_prelude] + [lua_test]
- out, err, exitCode = lit.util.executeCommand(cmd, env=lua_env)
+ out, err, exitCode = executeCommand(cmd, env=lua_env)
# Redirect Lua output
print(out)
Index: lldb/test/API/lua_api/TestComprehensive.lua
===================================================================
--- lldb/test/API/lua_api/TestComprehensive.lua
+++ lldb/test/API/lua_api/TestComprehensive.lua
@@ -69,6 +69,9 @@
local size = self.var_inited:GetByteSize()
local raw_data = self.process:ReadMemory(address:GetOffset(), size, error)
assertTrue(error:Success())
+ local data_le = lldb.SBData.CreateDataFromUInt32Array(lldb.eByteOrderLittle, 1, {0xDEADBEEF})
+ local data_be = lldb.SBData.CreateDataFromUInt32Array(lldb.eByteOrderBig, 1, {0xDEADBEEF})
+ assertTrue(data_le:GetUnsignedInt32(error, 0) == 0xDCADBEEF or data_be:GetUnsignedInt32(error, 0) == 0xDCADBEEF)
assertTrue(raw_data == "\xEF\xBE\xAD\xDE" or raw_data == "\xDE\xAD\xBE\xEF")
end
Index: lldb/bindings/lua/lua-typemaps.swig
===================================================================
--- lldb/bindings/lua/lua-typemaps.swig
+++ lldb/bindings/lua/lua-typemaps.swig
@@ -192,6 +192,8 @@
// Typemap for handling char ** in SBTarget::LaunchSimple, SBTarget::Launch...
+// It should accept a Lua table of strings, for stuff like "argv" and "envp".
+
%typemap(in) char ** {
if (lua_istable(L, $input)) {
size_t size = lua_rawlen(L, $input);
@@ -200,15 +202,19 @@
while (i++ < size) {
lua_rawgeti(L, $input, i);
if (!lua_isstring(L, -1)) {
+ // if current element cannot be converted to string, raise an error
lua_pop(L, 1);
- return luaL_error(L, "List should contains only strings");
+ return luaL_error(L, "List should only contain strings");
}
$1[j++] = (char *)lua_tostring(L, -1);
lua_pop(L, 1);
}
$1[j] = 0;
} else if (lua_isnil(L, $input)) {
+ // "nil" is also acceptable, equivalent as an empty table
$1 = NULL;
+ } else {
+ return luaL_error(L, "A list of strings expected");
}
}
@@ -261,21 +267,31 @@
(int32_t* array, size_t array_len),
(double* array, size_t array_len) {
if (lua_istable(L, $input)) {
+ // It should accept a table of numbers.
$2 = lua_rawlen(L, $input);
$1 = ($1_ltype)malloc(($2) * sizeof($*1_type));
int i = 0, j = 0;
while (i++ < $2) {
lua_rawgeti(L, $input, i);
+ if (!lua_isnumber(L, -1)) {
+ // if current element cannot be converted to number, raise an error
+ lua_pop(L, 1);
+ return luaL_error(L, "List should only contain numbers");
+ }
$1[j++] = ($*1_ltype)lua_tonumber(L, -1);
lua_pop(L, 1);
}
} else if (lua_isnil(L, $input)) {
+ // "nil" is also acceptable, equivalent as an empty table
$1 = NULL;
$2 = 0;
+ } else {
+ // else raise an error
+ return luaL_error(L, "A list of numbers expected.");
}
}
-%typemap(in) (uint64_t* array, size_t array_len),
+%typemap(freearg) (uint64_t* array, size_t array_len),
(uint32_t* array, size_t array_len),
(int64_t* array, size_t array_len),
(int32_t* array, size_t array_len),
Index: lldb/bindings/lua/CMakeLists.txt
===================================================================
--- lldb/bindings/lua/CMakeLists.txt
+++ lldb/bindings/lua/CMakeLists.txt
@@ -29,22 +29,43 @@
add_custom_target(${swig_target} ALL VERBATIM
COMMAND ${CMAKE_COMMAND} -E make_directory ${lldb_lua_target_dir}
DEPENDS swig_wrapper_lua
- COMMENT "Lua LLDB Python API")
- create_relative_symlink(${swig_target}
- "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/liblldb${CMAKE_SHARED_LIBRARY_SUFFIX}"
- ${lldb_lua_target_dir}
- "lldb.so")
+ COMMENT "LLDB Lua API")
+ if(LLDB_BUILD_FRAMEWORK)
+ set(LIBLLDB_SYMLINK_DEST "${LLDB_FRAMEWORK_ABSOLUTE_BUILD_DIR}/LLDB.framework/LLDB")
+ else()
+ set(LIBLLDB_SYMLINK_DEST "${LLVM_SHLIB_OUTPUT_INTDIR}/liblldb${CMAKE_SHARED_LIBRARY_SUFFIX}")
+ endif()
+ if(WIN32)
+ if(CMAKE_BUILD_TYPE STREQUAL Debug)
+ set(LIBLLDB_SYMLINK_OUTPUT_FILE "_lldb_d.pyd")
+ else()
+ set(LIBLLDB_SYMLINK_OUTPUT_FILE "_lldb.pyd")
+ endif()
+ else()
+ set(LIBLLDB_SYMLINK_OUTPUT_FILE "lldb.so")
+ endif()
+ create_relative_symlink(${swig_target} ${LIBLLDB_SYMLINK_DEST}
+ ${lldb_lua_target_dir} ${LIBLLDB_SYMLINK_OUTPUT_FILE})
set(lldb_lua_library_target "${swig_target}-library")
add_custom_target(${lldb_lua_library_target})
add_dependencies(${lldb_lua_library_target} ${swig_target})
+
+ # Ensure we do the Lua post-build step when building lldb.
+ add_dependencies(lldb ${swig_target})
+
+ if(LLDB_BUILD_FRAMEWORK)
+ set(LLDB_LUA_INSTALL_PATH ${LLDB_FRAMEWORK_INSTALL_DIR}/LLDB.framework/Resources/Python)
+ else()
+ set(LLDB_LUA_INSTALL_PATH ${LLDB_LUA_RELATIVE_PATH})
+ endif()
install(DIRECTORY ${lldb_lua_target_dir}/
DESTINATION ${LLDB_LUA_INSTALL_PATH}
COMPONENT ${lldb_lua_library_target})
- # Ensure we do the Lua post-build step when building lldb.
- add_dependencies(lldb ${swig_target})
set(lldb_lua_library_install_target "install-${lldb_lua_library_target}")
- add_llvm_install_targets(${lldb_lua_library_install_target}
- COMPONENT ${lldb_lua_library_target}
- DEPENDS ${lldb_lua_library_target})
+ if (NOT LLVM_ENABLE_IDE)
+ add_llvm_install_targets(${lldb_lua_library_install_target}
+ COMPONENT ${lldb_lua_library_target}
+ DEPENDS ${lldb_lua_library_target})
+ endif()
endfunction()
Index: lldb/CMakeLists.txt
===================================================================
--- lldb/CMakeLists.txt
+++ lldb/CMakeLists.txt
@@ -52,21 +52,10 @@
endif ()
if (LLDB_ENABLE_LUA)
- # FIXME: Lua 5.3 is hardcoded but it should support 5.3+!
- find_program(Lua_EXECUTABLE lua5.3)
- if (NOT Lua_EXECUTABLE)
- message(FATAL_ERROR "Lua executable not found")
- else ()
- execute_process(
- COMMAND ${Lua_EXECUTABLE}
- -e "for w in string.gmatch(package.cpath, ';?([^;]+);?') do \
- if string.match(w, '%?%.so') then print(string.sub(w, 1, #w - 4)) break end end"
- OUTPUT_VARIABLE LLDB_LUA_DEFAULT_INSTALL_PATH
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- file(TO_CMAKE_PATH ${LLDB_LUA_DEFAULT_INSTALL_PATH} LLDB_LUA_DEFAULT_INSTALL_PATH)
- set(LLDB_LUA_INSTALL_PATH ${LLDB_LUA_DEFAULT_INSTALL_PATH}
- CACHE STRING "Path where Lua modules are installed")
- endif ()
+ find_program(Lua_EXECUTABLE lua5.3)
+ set(LLDB_LUA_DEFAULT_RELATIVE_PATH "lib/lua/5.3")
+ set(LLDB_LUA_RELATIVE_PATH ${LLDB_LUA_DEFAULT_RELATIVE_PATH}
+ CACHE STRING "Path where Lua modules are installed, relative to install prefix")
endif ()
if (LLDB_ENABLE_PYTHON OR LLDB_ENABLE_LUA)
@@ -113,7 +102,11 @@
endif()
if (LLDB_ENABLE_LUA)
- set(lldb_lua_target_dir "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${CMAKE_INSTALL_LIBDIR}/lua")
+ if(LLDB_BUILD_FRAMEWORK)
+ set(lldb_lua_target_dir "${LLDB_FRAMEWORK_ABSOLUTE_BUILD_DIR}/LLDB.framework/Resources/Lua")
+ else()
+ set(lldb_lua_target_dir "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${LLDB_LUA_RELATIVE_PATH}")
+ endif()
get_target_property(lldb_lua_bindings_dir swig_wrapper_lua BINARY_DIR)
finish_swig_lua("lldb-lua" "${lldb_lua_bindings_dir}" "${lldb_lua_target_dir}")
endif()
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits