diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f8dab5f..528172b9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,12 +17,9 @@ jobs: - "5.3" - "5.4" - "luajit-2.0.5" + - "luajit-2.1.0-beta3" steps: - uses: actions/checkout@v3 - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: "3.10" - name: Install Lua uses: leafo/gh-actions-lua@v10 with: diff --git a/.gitignore b/.gitignore index f3f7b6ab..d0761c62 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,7 @@ tests/c/doctest.h src/constants/ src/registers.cpp src/registers_const.cpp -include/unicornlua/register_types.h +include/unicornlua/register_types.hpp # Other garbage core* diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 13901b12..825d6930 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,11 +1,21 @@ Changes ======= -Unreleased ----------- +2.2.0 (Unreleased) +------------------ + +New Features +~~~~~~~~~~~~ + +Official support for LuaJIT 2.1. + +Other Changes +~~~~~~~~~~~~~ -* Autogenerate a bunch of register-related files from templates. * Add clang-format, use WebKit's style (more or less). +* Autogenerate a bunch of register-related files from templates. **Note:** Some + register type enums values have changed. If you use the symbolic constants + provided in ``registers_const`` this won't affect you. 2.1.0 (2023-04-08) ------------------ diff --git a/Makefile b/Makefile index a9af61e0..cfbeb4b3 100644 --- a/Makefile +++ b/Makefile @@ -13,6 +13,7 @@ LIB_EXTENSION ?= so LUA ?= lua LUA_DIR ?= /usr/local LUAROCKS ?= luarocks +MKDIR ?= mkdir OBJ_EXTENSION ?= o UNICORN_INCDIR ?= /usr/include @@ -32,8 +33,10 @@ endif IS_LUAJIT = $(shell $(LUA) -e 'if _G.jit ~= nil then print(1) else print(0) end') ifeq ($(IS_LUAJIT),1) DEFAULT_LUA_LIB_NAME := luajit-5.1 - # FIXME (dargueta): This will break on LuaJIT 2.1 - FALLBACK_LUA_INCDIR := $(LUA_DIR)/include/luajit-2.0 + LUAJIT_VERSION := $(shell \ + $(LUA) -e 'print(string.format("%d.%d", jit.version_num / 10000, (jit.version_num / 100) % 100))' \ + ) + FALLBACK_LUA_INCDIR := $(LUA_DIR)/include/luajit-$(LUAJIT_VERSION) else DEFAULT_LUA_LIB_NAME := lua FALLBACK_LUA_INCDIR := $(LUA_DIR)/include @@ -49,12 +52,11 @@ ARCHITECTURE_SLUGS = $(filter-out platform,$(basename $(notdir $(ARCHITECTURE_HE CONSTS_DIR = src/constants CONSTANT_FILES = $(foreach s,$(ARCHITECTURE_SLUGS),$(CONSTS_DIR)/$(s)_const.cpp) -CPP_TEMPLATE_SOURCES := src/registers_const.template \ - src/registers.template +CPP_TEMPLATE_SOURCES := $(wildcard src/*.template) AUTOGENERATED_CPP_FILES = $(CPP_TEMPLATE_SOURCES:.template=.cpp) -HEADER_TEMPLATE_SOURCES := include/unicornlua/register_types.template -AUTOGENERATED_HEADER_FILES = $(HEADER_TEMPLATE_SOURCES:.template=.h) +HEADER_TEMPLATE_SOURCES := $(wildcard include/unicornlua/*.template) +AUTOGENERATED_HPP_FILES = $(HEADER_TEMPLATE_SOURCES:.template=.hpp) LIB_BUILD_TARGET := $(BUILD_DIR)/unicorn.$(LIB_EXTENSION) LIB_CPP_SOURCES = $(wildcard src/*.cpp) $(CONSTANT_FILES) $(AUTOGENERATED_CPP_FILES) @@ -63,7 +65,7 @@ LIB_OBJECT_FILES = $(LIB_CPP_SOURCES:.cpp=.$(OBJ_EXTENSION)) TEST_EXECUTABLE := $(BUILD_DIR)/cpp_test TEST_CPP_SOURCES = $(wildcard tests/c/*.cpp) TEST_LUA_SOURCES = $(wildcard tests/lua/*.lua) -TEST_HEADERS = $(wildcard tests/c/*.h) +TEST_HEADERS = $(wildcard tests/c/*.hpp) TEST_CPP_OBJECT_FILES = $(TEST_CPP_SOURCES:.cpp=.$(OBJ_EXTENSION)) LIBRARY_DIRECTORIES := $(strip $(LUA_LIBDIR) $(FALLBACK_LUA_LIBDIR) $(UNICORN_LIBDIR) $(PTHREAD_LIBDIR) /usr/lib64 /usr/local/lib) @@ -86,7 +88,10 @@ LINK_TO_LUA_FLAG := $(if $(LUALIB),-l:$(LUALIB),-l$(DEFAULT_LUA_LIB_NAME)) OS ?= $(shell uname -s) ifeq ($(OS),Darwin) ifeq ($(IS_LUAJIT),1) - LINK_TO_LUA_FLAG += -pagezero_size 10000 -image_base 100000000 + # This workaround isn't needed for LuaJIT 2.1+ + ifeq ($(LUAJIT_VERSION),2.0) + LINK_TO_LUA_FLAG += -pagezero_size 10000 -image_base 100000000 + endif endif endif @@ -109,7 +114,7 @@ DOCTEST_TAG := v2.4.11 DOCTEST_HEADER := tests/c/doctest.h # Uncomment for debugging autogenerated files -# .PRECIOUS: $(AUTOGENERATED_CPP_FILES) $(AUTOGENERATED_HEADER_FILES) $(CONSTANT_FILES) +# .PRECIOUS: $(AUTOGENERATED_CPP_FILES) $(AUTOGENERATED_HPP_FILES) $(CONSTANT_FILES) .PHONY: all all: $(LIB_BUILD_TARGET) $(TEST_EXECUTABLE) @@ -124,7 +129,7 @@ install: $(LIB_BUILD_TARGET) clean: $(RM) $(LIB_OBJECT_FILES) $(CONSTANT_FILES) $(LIB_BUILD_TARGET) $(RM) $(TEST_EXECUTABLE) $(TEST_CPP_OBJECT_FILES) $(DOCTEST_HEADER) - $(RM) -r $(BUILD_DIR) $(CONSTS_DIR) $(AUTOGENERATED_CPP_FILES) $(AUTOGENERATED_HEADER_FILES) + $(RM) -r $(BUILD_DIR) $(CONSTS_DIR) $(AUTOGENERATED_CPP_FILES) $(AUTOGENERATED_HPP_FILES) .PHONY: test @@ -139,6 +144,21 @@ test: $(TEST_EXECUTABLE) $(TEST_LUA_SOURCES) tests/lua +.PHONY: autoformat +autoformat: + @clang-format --Werror -i --verbose \ + $(filter-out $(AUTOGENERATED_CPP_FILES),$(wildcard src/*.cpp)) \ + $(filter-out $(AUTOGENERATED_HPP_FILES),$(wildcard include/unicornlua/*.hpp)) \ + $(wildcard tests/c/*.cpp) \ + $(wildcard tests/c/*.hpp) + + +# Convenience target for generating all templated files. This is mostly for +# making IDEs and linters shut up about "missing" files. +.PHONY: autogen-files +autogen-files: $(AUTOGENERATED_CPP_FILES) $(AUTOGENERATED_HPP_FILES) $(CONSTANT_FILES) + + $(DOCTEST_HEADER): $(CURL) -sSo $@ https://raw.githubusercontent.com/doctest/doctest/$(DOCTEST_TAG)/doctest/doctest.h @@ -148,11 +168,12 @@ $(LIB_BUILD_TARGET): $(LIB_OBJECT_FILES) | $(BUILD_DIR) $(TEST_EXECUTABLE): $(DOCTEST_HEADER) $(TEST_CPP_OBJECT_FILES) $(LIB_OBJECT_FILES) $(TEST_HEADERS) - $(LINK_CMD) -o $@ $(filter-out %.h,$^) $(REQUIRED_LIBS_FLAGS) $(LINK_TO_LUA_FLAG) -lm + $(LINK_CMD) -o $@ $(filter %.$(OBJ_EXTENSION),$^) $(REQUIRED_LIBS_FLAGS) $(LINK_TO_LUA_FLAG) -lm $(CONSTS_DIR)/%_const.cpp: $(UNICORN_INCDIR)/unicorn/%.h | $(CONSTS_DIR) - $(SET_SEARCH_PATHS); $(LUA) tools/generate_constants.lua $< $@ + @echo "Generating $@" + @$(SET_SEARCH_PATHS); $(LUA) tools/generate_constants.lua $< $@ # We're deliberately omitting CXXFLAGS as provided by LuaRocks because it includes @@ -161,16 +182,18 @@ tests/c/%.$(OBJ_EXTENSION): tests/c/%.cpp $(CXX_CMD) -c -o $@ $^ -src/%.$(OBJ_EXTENSION): src/%.cpp $(AUTOGENERATED_HEADER_FILES) +src/%.$(OBJ_EXTENSION): src/%.cpp $(AUTOGENERATED_HPP_FILES) $(CXX_CMD) $(CXXFLAGS) -c -o $@ $< %.cpp: %.template src/register_types.lua - $(LUA) tools/render_template.lua -o $@ $^ + @echo "Generating $@" + @$(SET_SEARCH_PATHS); $(LUA) tools/render_template.lua -o $@ $^ -%.h: %.template src/register_types.lua - $(LUA) tools/render_template.lua -o $@ $^ +%.hpp: %.template src/register_types.lua + @echo "Generating $@" + @$(SET_SEARCH_PATHS); $(LUA) tools/render_template.lua -o $@ $^ $(CONSTS_DIR) $(BUILD_DIR): diff --git a/README.rst b/README.rst index f6a628d9..c91bbc87 100644 --- a/README.rst +++ b/README.rst @@ -7,7 +7,7 @@ unicorn-lua :alt: Build status :target: https://travis-ci.com/dargueta/unicorn-lua -.. |lua-versions| image:: https://img.shields.io/badge/lua-5.1%20%7C%205.2%20%7C%205.3%20%7C%205.4%20%7C%20LuaJIT2.0-blue +.. |lua-versions| image:: https://img.shields.io/badge/lua-5.1%20%7C%205.2%20%7C%205.3%20%7C%205.4%20%7C%20LuaJIT2.020%7C%20LuaJIT2.1-blue-blue :alt: Lua versions :target: https://www.lua.org @@ -16,8 +16,8 @@ unicorn-lua Lua bindings for the `Unicorn CPU Emulator`_. -I'm currently testing this on vanilla Lua 5.1 - 5.4, and LuaJIT 2.0 on both Linux -and OSX. +I'm currently testing this on vanilla Lua 5.1 - 5.4, LuaJIT 2.0, and LuaJIT 2.1 on +both Linux and MacOS. License Change -------------- diff --git a/include/unicornlua/compat.h b/include/unicornlua/compat.hpp similarity index 91% rename from include/unicornlua/compat.h rename to include/unicornlua/compat.hpp index 7c3ca6d5..012d2827 100644 --- a/include/unicornlua/compat.h +++ b/include/unicornlua/compat.hpp @@ -1,7 +1,7 @@ /** * Compatibility shims for differences between Lua versions. * - * @file compat.h + * @file compat.hpp */ #pragma once @@ -42,10 +42,15 @@ LUALIB_API void luaL_setfuncs(lua_State* L, const luaL_Reg* l, int nup); LUALIB_API void lua_rawsetp(lua_State* L, int index, const void* p); +#ifndef luaL_newlibtable #define luaL_newlibtable(L, l) lua_createtable((L), 0, sizeof(l) / sizeof(*(l))) +#endif // luaL_newlibtable + +#ifndef luaL_newlib #define luaL_newlib(L, l) \ (luaL_newlibtable((L), (l)), luaL_setfuncs((L), (l), 0)) -#endif +#endif // luaL_newlib +#endif // LUA_VERSION_NUM < 502 // http://lua-users.org/lists/lua-l/2011-11/msg01149.html #ifndef IS_LUAJIT diff --git a/include/unicornlua/context.h b/include/unicornlua/context.hpp similarity index 72% rename from include/unicornlua/context.h rename to include/unicornlua/context.hpp index d53844af..f711bf2a 100644 --- a/include/unicornlua/context.h +++ b/include/unicornlua/context.hpp @@ -1,15 +1,15 @@ /** * Lua bindings for Unicorn context operations. * - * @file context.h + * @file context.hpp */ #pragma once #include -#include "unicornlua/engine.h" -#include "unicornlua/lua.h" +#include "unicornlua/engine.hpp" +#include "unicornlua/lua.hpp" extern const char* const kContextMetatableName; extern const luaL_Reg kContextMetamethods[]; @@ -37,6 +37,4 @@ int ul_context_free(lua_State* L); */ int ul_context_maybe_free(lua_State* L); -#define get_context_struct(L, index) \ - (reinterpret_cast( \ - luaL_checkudata((L), (index), kContextMetatableName))) +Context* ul_toluacontext(lua_State* L, int index); diff --git a/include/unicornlua/engine.h b/include/unicornlua/engine.hpp similarity index 84% rename from include/unicornlua/engine.h rename to include/unicornlua/engine.hpp index e7a778ef..ed2200a7 100644 --- a/include/unicornlua/engine.h +++ b/include/unicornlua/engine.hpp @@ -10,14 +10,16 @@ #include -#include "unicornlua/hooks.h" -#include "unicornlua/lua.h" -#include "unicornlua/utils.h" +#include "unicornlua/hooks.hpp" +#include "unicornlua/lua.hpp" +#include "unicornlua/utils.hpp" extern const char* const kEngineMetatableName; extern const char* const kEnginePointerMapName; +extern "C" { extern const luaL_Reg kEngineInstanceMethods[]; extern const luaL_Reg kEngineMetamethods[]; +} struct Context; @@ -79,7 +81,7 @@ class UCLuaEngine { * @param L A pointer to the current Lua state. * @param engine A pointer to the engine we want to get the Lua object for. */ -void ul_get_engine_object(lua_State* L, const uc_engine* engine); +void ul_find_lua_engine(lua_State* L, const uc_engine* engine); /** * Initialize the engine object internals, such as registering metatables. @@ -99,17 +101,25 @@ void ul_init_engines_lib(lua_State* L); * @param L A pointer to the current Lua state. * @param index The index on the Lua stack of the value to convert. * - * @return The engine. + * @return The low-level Unicorn engine. */ uc_engine* ul_toengine(lua_State* L, int index); -#define get_engine_struct(L, index) \ - reinterpret_cast( \ - luaL_checkudata((L), (index), kEngineMetatableName)) +/** + * Return the value on the stack at @a index as a pointer to a @ref UCLuaEngine. + * + * If the value at @a index is @e not a @ref UCLuaEngine, a Lua error will be + * thrown. + * + * @param L A pointer to the current Lua state. + * @param index The index on the Lua stack of the value to convert. + * + * @return The engine. + */ +UCLuaEngine* ul_toluaengine(lua_State* L, int index); int ul_close(lua_State* L); int ul_query(lua_State* L); int ul_errno(lua_State* L); int ul_emu_start(lua_State* L); int ul_emu_stop(lua_State* L); -uc_engine* ul_toengine(lua_State* L, int index); diff --git a/include/unicornlua/errors.h b/include/unicornlua/errors.hpp similarity index 97% rename from include/unicornlua/errors.h rename to include/unicornlua/errors.hpp index e0eec8e5..c3f64c5d 100644 --- a/include/unicornlua/errors.h +++ b/include/unicornlua/errors.hpp @@ -10,7 +10,7 @@ #include -#include "unicornlua/lua.h" +#include "unicornlua/lua.hpp" /** * Exception class for translating Unicorn error codes into C++ exceptions. diff --git a/include/unicornlua/hooks.h b/include/unicornlua/hooks.hpp similarity index 98% rename from include/unicornlua/hooks.h rename to include/unicornlua/hooks.hpp index 46e9ac30..7d47dab0 100644 --- a/include/unicornlua/hooks.h +++ b/include/unicornlua/hooks.hpp @@ -6,7 +6,7 @@ #include -#include "unicornlua/lua.h" +#include "unicornlua/lua.hpp" class Hook { friend class UCLuaEngine; diff --git a/include/unicornlua/lua.h b/include/unicornlua/lua.hpp similarity index 86% rename from include/unicornlua/lua.h rename to include/unicornlua/lua.hpp index b66266f1..f3bb2829 100644 --- a/include/unicornlua/lua.h +++ b/include/unicornlua/lua.hpp @@ -9,4 +9,4 @@ extern "C" { #include } -#include "compat.h" +#include "compat.hpp" diff --git a/include/unicornlua/memory.h b/include/unicornlua/memory.hpp similarity index 93% rename from include/unicornlua/memory.h rename to include/unicornlua/memory.hpp index 35eb23b1..bfb37a70 100644 --- a/include/unicornlua/memory.h +++ b/include/unicornlua/memory.hpp @@ -6,7 +6,7 @@ #pragma once -#include "unicornlua/lua.h" +#include "unicornlua/lua.hpp" /** * Write data to a location in a machine's memory. diff --git a/include/unicornlua/register_template_functions.h b/include/unicornlua/register_template_functions.hpp similarity index 99% rename from include/unicornlua/register_template_functions.h rename to include/unicornlua/register_template_functions.hpp index d2fa7bcf..77d7a726 100644 --- a/include/unicornlua/register_template_functions.h +++ b/include/unicornlua/register_template_functions.hpp @@ -7,7 +7,7 @@ #include #include "lua.h" -#include "registers.h" +#include "registers.hpp" template void integer_array_to_table(lua_State* L, const std::array& arr) diff --git a/include/unicornlua/registers.h b/include/unicornlua/registers.hpp similarity index 99% rename from include/unicornlua/registers.h rename to include/unicornlua/registers.hpp index cebcb711..c4d0e205 100644 --- a/include/unicornlua/registers.h +++ b/include/unicornlua/registers.hpp @@ -11,8 +11,8 @@ #include #include -#include "unicornlua/lua.h" -#include "unicornlua/register_types.h" +#include "unicornlua/lua.hpp" +#include "unicornlua/register_types.hpp" #if FLT_RADIX != 2 #error "Can't handle floating-point radixes other than 2 right now." diff --git a/include/unicornlua/unicornlua.h b/include/unicornlua/unicornlua.hpp similarity index 95% rename from include/unicornlua/unicornlua.h rename to include/unicornlua/unicornlua.hpp index dd9b3ab6..95f08444 100644 --- a/include/unicornlua/unicornlua.h +++ b/include/unicornlua/unicornlua.hpp @@ -8,8 +8,8 @@ #include -#include "unicornlua/compat.h" -#include "unicornlua/lua.h" +#include "unicornlua/compat.hpp" +#include "unicornlua/lua.hpp" #if UC_VERSION_MAJOR != 1 #error "Library must be compiled against version 1.x of Unicorn." @@ -23,7 +23,7 @@ /** * The minor version number of this Lua library (second part, x.1.x). */ -#define UNICORNLUA_VERSION_MINOR 1 +#define UNICORNLUA_VERSION_MINOR 2 /** * The patch version number of this Lua library (third part, x.x.1). diff --git a/include/unicornlua/utils.h b/include/unicornlua/utils.hpp similarity index 97% rename from include/unicornlua/utils.h rename to include/unicornlua/utils.hpp index 7e521832..4a82092a 100644 --- a/include/unicornlua/utils.h +++ b/include/unicornlua/utils.hpp @@ -11,7 +11,7 @@ #include -#include "unicornlua/lua.h" +#include "unicornlua/lua.hpp" /** * Throw a Lua error with a message derived from the given Unicorn error code. diff --git a/unicorn-2.1.0-1.rockspec b/rockspecs/unicorn-2.1.0-1.rockspec similarity index 100% rename from unicorn-2.1.0-1.rockspec rename to rockspecs/unicorn-2.1.0-1.rockspec diff --git a/src/compat.cpp b/src/compat.cpp index 23b9f85e..f2b837ed 100644 --- a/src/compat.cpp +++ b/src/compat.cpp @@ -1,5 +1,5 @@ -#include "unicornlua/compat.h" -#include "unicornlua/lua.h" +#include "unicornlua/compat.hpp" +#include "unicornlua/lua.hpp" #if LUA_VERSION_NUM < 503 diff --git a/src/context.cpp b/src/context.cpp index 3c41c4a7..b023fa79 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -1,9 +1,9 @@ #include -#include "unicornlua/context.h" -#include "unicornlua/engine.h" -#include "unicornlua/errors.h" -#include "unicornlua/utils.h" +#include "unicornlua/context.hpp" +#include "unicornlua/engine.hpp" +#include "unicornlua/errors.hpp" +#include "unicornlua/utils.hpp" const char* const kContextMetatableName = "unicornlua__context_meta"; @@ -13,16 +13,22 @@ const luaL_Reg kContextMetamethods[] = { { "__gc", ul_context_maybe_free }, const luaL_Reg kContextInstanceMethods[] = { { "free", ul_context_free }, { nullptr, nullptr } }; +Context* ul_toluacontext(lua_State* L, int index) +{ + return reinterpret_cast( + luaL_checkudata(L, index, kContextMetatableName)); +} + int ul_context_save(lua_State* L) { - auto engine = get_engine_struct(L, 1); + UCLuaEngine* engine = ul_toluaengine(L, 1); if (lua_gettop(L) < 2) { // Caller didn't provide a context, create a new one and push it to the // stack so we can return it to the caller. engine->create_context_in_lua(); } else { - Context* context = get_context_struct(L, 2); + Context* context = ul_toluacontext(L, 2); if (context->context_handle == nullptr) throw LuaBindingError("Cannot update a closed context."); @@ -33,15 +39,15 @@ int ul_context_save(lua_State* L) int ul_context_restore(lua_State* L) { - auto engine = get_engine_struct(L, 1); - Context* context = get_context_struct(L, 2); + UCLuaEngine* engine = ul_toluaengine(L, 1); + Context* context = ul_toluacontext(L, 2); engine->restore_from_context(context); return 0; } int ul_context_free(lua_State* L) { - Context* context = get_context_struct(L, 1); + Context* context = ul_toluacontext(L, 1); if (context->context_handle == nullptr) throw LuaBindingError("Attempted to free the same context twice."); @@ -56,7 +62,7 @@ int ul_context_free(lua_State* L) int ul_context_maybe_free(lua_State* L) { - Context* context = get_context_struct(L, 1); + Context* context = ul_toluacontext(L, 1); // Do nothing if the context has already been freed. if (context->context_handle != nullptr) diff --git a/src/engine.cpp b/src/engine.cpp index 6345ae93..eae8ac9f 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -1,14 +1,14 @@ #include -#include "unicornlua/context.h" -#include "unicornlua/engine.h" -#include "unicornlua/errors.h" -#include "unicornlua/hooks.h" -#include "unicornlua/lua.h" -#include "unicornlua/memory.h" -#include "unicornlua/registers.h" -#include "unicornlua/unicornlua.h" -#include "unicornlua/utils.h" +#include "unicornlua/context.hpp" +#include "unicornlua/engine.hpp" +#include "unicornlua/errors.hpp" +#include "unicornlua/hooks.hpp" +#include "unicornlua/lua.hpp" +#include "unicornlua/memory.hpp" +#include "unicornlua/registers.hpp" +#include "unicornlua/unicornlua.hpp" +#include "unicornlua/utils.hpp" const char* const kEngineMetatableName = "unicornlua__engine_meta"; const char* const kEnginePointerMapName = "unicornlua__engine_ptr_map"; @@ -16,7 +16,7 @@ const char* const kEnginePointerMapName = "unicornlua__engine_ptr_map"; // Close the engine only if it hasn't been closed already. static int maybe_close(lua_State* L) { - UCLuaEngine* engine_object = get_engine_struct(L, 1); + UCLuaEngine* engine_object = ul_toluaengine(L, 1); uc_engine* engine_handle = engine_object->get_handle(); if (engine_handle != nullptr) @@ -24,6 +24,7 @@ static int maybe_close(lua_State* L) return 0; } +extern "C" { const luaL_Reg kEngineMetamethods[] = { { "__gc", maybe_close }, { "__close", maybe_close }, { nullptr, nullptr } }; @@ -40,6 +41,13 @@ const luaL_Reg kEngineInstanceMethods[] = { { "close", ul_close }, { "reg_read_batch_as", ul_reg_read_batch_as }, { "reg_write", ul_reg_write }, { "reg_write_as", ul_reg_write_as }, { "reg_write_batch", ul_reg_write_batch }, { nullptr, nullptr } }; +} + +UCLuaEngine* ul_toluaengine(lua_State* L, int index) +{ + return reinterpret_cast( + luaL_checkudata(L, index, kEngineMetatableName)); +} UCLuaEngine::UCLuaEngine(lua_State* L, uc_engine* engine) : L_(L) @@ -183,7 +191,7 @@ void UCLuaEngine::free_context(Context* context) uc_err error; -#if UNICORNLUA_UNICORN_MAJOR_MINOR_PATCH >= 0x010002 +#if UNICORNLUA_UNICORN_MAJOR_MINOR_PATCH >= MAKE_VERSION(1, 0, 2) /* Unicorn 1.0.2 added its own separate function for freeing contexts. */ error = uc_context_free(context->context_handle); #else @@ -224,7 +232,7 @@ void ul_init_engines_lib(lua_State* L) lua_pop(L, 2); } -void ul_get_engine_object(lua_State* L, const uc_engine* engine) +void ul_find_lua_engine(lua_State* L, const uc_engine* engine) { lua_getfield(L, LUA_REGISTRYINDEX, kEnginePointerMapName); lua_pushlightuserdata(L, (void*)engine); @@ -234,8 +242,7 @@ void ul_get_engine_object(lua_State* L, const uc_engine* engine) // Remove nil and engine pointer map at TOS lua_pop(L, 2); throw LuaBindingError("No engine object is registered for the given " - "pointer. It may have been" - " deleted already."); + "pointer. It may have been deleted already."); } // Remove the engine pointer map from the stack. @@ -244,7 +251,7 @@ void ul_get_engine_object(lua_State* L, const uc_engine* engine) int ul_close(lua_State* L) { - UCLuaEngine* engine_object = get_engine_struct(L, 1); + UCLuaEngine* engine_object = ul_toluaengine(L, 1); uc_engine* engine_handle = engine_object->get_handle(); if (engine_handle == nullptr) @@ -265,7 +272,7 @@ int ul_close(lua_State* L) int ul_query(lua_State* L) { - const UCLuaEngine* engine_object = get_engine_struct(L, 1); + const UCLuaEngine* engine_object = ul_toluaengine(L, 1); auto query_type = static_cast(luaL_checkinteger(L, 2)); size_t result = engine_object->query(query_type); @@ -275,14 +282,14 @@ int ul_query(lua_State* L) int ul_errno(lua_State* L) { - const UCLuaEngine* engine = get_engine_struct(L, 1); + const UCLuaEngine* engine = ul_toluaengine(L, 1); lua_pushinteger(L, engine->get_errno()); return 1; } int ul_emu_start(lua_State* L) { - UCLuaEngine* engine = get_engine_struct(L, 1); + UCLuaEngine* engine = ul_toluaengine(L, 1); auto start = static_cast(luaL_checkinteger(L, 2)); auto end = static_cast(luaL_checkinteger(L, 3)); auto timeout = static_cast(luaL_optinteger(L, 4, 0)); @@ -294,14 +301,14 @@ int ul_emu_start(lua_State* L) int ul_emu_stop(lua_State* L) { - UCLuaEngine* engine = get_engine_struct(L, 1); + UCLuaEngine* engine = ul_toluaengine(L, 1); engine->stop(); return 0; } uc_engine* ul_toengine(lua_State* L, int index) { - const UCLuaEngine* engine_object = get_engine_struct(L, index); + const UCLuaEngine* engine_object = ul_toluaengine(L, index); uc_engine* engine_handle = engine_object->get_handle(); if (engine_handle == nullptr) diff --git a/src/errors.cpp b/src/errors.cpp index 7813ecd7..c492eb95 100644 --- a/src/errors.cpp +++ b/src/errors.cpp @@ -2,8 +2,8 @@ #include -#include "unicornlua/errors.h" -#include "unicornlua/lua.h" +#include "unicornlua/errors.hpp" +#include "unicornlua/lua.hpp" UnicornLibraryError::UnicornLibraryError(uc_err error) : std::runtime_error(uc_strerror(error)) diff --git a/src/hooks.cpp b/src/hooks.cpp index 7f1bda7a..cc3e8a2f 100644 --- a/src/hooks.cpp +++ b/src/hooks.cpp @@ -1,11 +1,11 @@ #include #include -#include "unicornlua/engine.h" -#include "unicornlua/errors.h" -#include "unicornlua/hooks.h" -#include "unicornlua/lua.h" -#include "unicornlua/utils.h" +#include "unicornlua/engine.hpp" +#include "unicornlua/errors.hpp" +#include "unicornlua/hooks.hpp" +#include "unicornlua/lua.hpp" +#include "unicornlua/utils.hpp" Hook::Hook(lua_State* L, uc_engine* engine) : L_(L) @@ -94,10 +94,11 @@ static void get_callback(Hook* hook) { lua_State* L = hook->L(); hook->push_callback(); - if (lua_isnil(L, -1)) + if (lua_isnil(L, -1)) { luaL_error(L, "No callback function found for hook %p attached to engine %p", hook, hook->engine()); + } } /* The C wrapper for a code execution hook. */ @@ -111,7 +112,7 @@ static void code_hook( get_callback(hook); /* Push the arguments */ - ul_get_engine_object(L, uc); + ul_find_lua_engine(L, uc); lua_pushinteger(L, static_cast(address)); lua_pushinteger(L, static_cast(size)); hook->push_user_data(); @@ -127,7 +128,7 @@ static void interrupt_hook(uc_engine* uc, uint32_t intno, void* user_data) get_callback(hook); /* Push the arguments */ - ul_get_engine_object(L, uc); + ul_find_lua_engine(L, uc); lua_pushinteger(L, static_cast(intno)); hook->push_user_data(); lua_call(L, 3, 0); @@ -143,7 +144,7 @@ static uint32_t port_in_hook( get_callback(hook); /* Push the arguments */ - ul_get_engine_object(L, uc); + ul_find_lua_engine(L, uc); lua_pushinteger(L, static_cast(port)); lua_pushinteger(L, static_cast(size)); hook->push_user_data(); @@ -165,7 +166,7 @@ static void port_out_hook( get_callback(hook); /* Push the arguments */ - ul_get_engine_object(L, uc); + ul_find_lua_engine(L, uc); lua_pushinteger(L, static_cast(port)); lua_pushinteger(L, static_cast(size)); lua_pushinteger(L, static_cast(value)); @@ -183,7 +184,7 @@ static void memory_access_hook(uc_engine* uc, uc_mem_type type, get_callback(hook); /* Push the arguments */ - ul_get_engine_object(L, uc); + ul_find_lua_engine(L, uc); lua_pushinteger(L, (lua_Integer)type); lua_pushinteger(L, static_cast(address)); lua_pushinteger(L, static_cast(size)); @@ -202,7 +203,7 @@ static bool invalid_mem_access_hook(uc_engine* uc, uc_mem_type type, get_callback(hook); /* Push the arguments */ - ul_get_engine_object(L, uc); + ul_find_lua_engine(L, uc); lua_pushinteger(L, static_cast(type)); lua_pushinteger(L, static_cast(address)); lua_pushinteger(L, static_cast(size)); @@ -213,8 +214,7 @@ static bool invalid_mem_access_hook(uc_engine* uc, uc_mem_type type, if (lua_type(L, -1) != LUA_TBOOLEAN) { luaL_error(L, "Error: Handler for invalid memory accesses must return a boolean, " - "got a %s" - " instead.", + "got a %s instead.", lua_typename(L, -1)); // Technically this is unreachable because luaL_error calls longjmp(). // The header doesn't declare this, however, so we have no way of @@ -240,7 +240,7 @@ static void* get_c_callback_for_hook_type(int hook_type, int insn_code) /* TODO (dargueta): Support other architectures beside X86. */ if (insn_code == UC_X86_INS_IN) return (void*)port_in_hook; - else if (insn_code == UC_X86_INS_OUT) + if (insn_code == UC_X86_INS_OUT) return (void*)port_out_hook; return (void*)code_hook; @@ -278,7 +278,7 @@ int ul_hook_add(lua_State* L) int n_args = lua_gettop(L); - auto engine_object = get_engine_struct(L, 1); + UCLuaEngine* engine_object = ul_toluaengine(L, 1); int hook_type = static_cast(luaL_checkinteger(L, 2)); /* Callback function is at position 3 */ @@ -355,7 +355,7 @@ int ul_hook_add(lua_State* L) int ul_hook_del(lua_State* L) { auto hook_info = (Hook*)lua_touserdata(L, 2); - auto engine = get_engine_struct(L, 1); + UCLuaEngine* engine = ul_toluaengine(L, 1); engine->remove_hook(hook_info); return 0; diff --git a/src/memory.cpp b/src/memory.cpp index 2402a723..a58f0ad3 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -2,10 +2,10 @@ #include -#include "unicornlua/compat.h" -#include "unicornlua/engine.h" -#include "unicornlua/lua.h" -#include "unicornlua/utils.h" +#include "unicornlua/compat.hpp" +#include "unicornlua/engine.hpp" +#include "unicornlua/lua.hpp" +#include "unicornlua/utils.hpp" int ul_mem_write(lua_State* L) { diff --git a/src/registers.template b/src/registers.template index 0743876c..434c6e5c 100644 --- a/src/registers.template +++ b/src/registers.template @@ -1,9 +1,9 @@ #include -#include "unicornlua/errors.h" -#include "unicornlua/lua.h" -#include "unicornlua/registers.h" -#include "unicornlua/register_template_functions.h" +#include "unicornlua/errors.hpp" +#include "unicornlua/lua.hpp" +#include "unicornlua/registers.hpp" +#include "unicornlua/register_template_functions.hpp" @ for _, bits in ipairs({8, 16, 32, 64}) do diff --git a/src/registers_const.template b/src/registers_const.template index ec8c8578..b7888df7 100644 --- a/src/registers_const.template +++ b/src/registers_const.template @@ -1,8 +1,8 @@ #include -#include "unicornlua/lua.h" -#include "unicornlua/registers.h" -#include "unicornlua/utils.h" +#include "unicornlua/lua.hpp" +#include "unicornlua/registers.hpp" +#include "unicornlua/utils.hpp" static const struct NamedIntConst kConstants[] { diff --git a/src/registers_misc.cpp b/src/registers_misc.cpp index d738a51d..a0030b0b 100644 --- a/src/registers_misc.cpp +++ b/src/registers_misc.cpp @@ -12,12 +12,12 @@ #include #include -#include "unicornlua/compat.h" -#include "unicornlua/engine.h" -#include "unicornlua/errors.h" -#include "unicornlua/lua.h" -#include "unicornlua/registers.h" -#include "unicornlua/utils.h" +#include "unicornlua/compat.hpp" +#include "unicornlua/engine.hpp" +#include "unicornlua/errors.hpp" +#include "unicornlua/lua.hpp" +#include "unicornlua/registers.hpp" +#include "unicornlua/utils.hpp" const uint8_t kFP80PositiveInfinity[] = { 0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0x7f }; @@ -151,10 +151,9 @@ void write_float80(lua_Number value, uint8_t* buffer) break; default: throw std::runtime_error("Unrecognized value returned from " - "std::fpclassify(). This library was" - " probably compiled on a newer standard of " - "C++ than it was written for." - " Please file a bug ticket."); + "std::fpclassify(). This library was probably " + "compiled on a newer standard of C++ than it " + "was written for. Please file a bug ticket."); } int exponent; @@ -162,8 +161,8 @@ void write_float80(lua_Number value, uint8_t* buffer) if ((exponent <= -16383) || (exponent >= 16384)) throw std::domain_error("Can't convert value outside representable " - "range for 80-bit float without" - " loss of precision."); + "range for 80-bit float without loss of " + "precision."); // The high bit of the significand is always set for normal numbers, and // clear for denormal numbers. This means the significand is 63 bits, not diff --git a/src/unicorn.cpp b/src/unicorn.cpp index 71bc911d..c5c5cd96 100644 --- a/src/unicorn.cpp +++ b/src/unicorn.cpp @@ -1,10 +1,10 @@ #include -#include "unicornlua/context.h" -#include "unicornlua/engine.h" -#include "unicornlua/lua.h" -#include "unicornlua/unicornlua.h" -#include "unicornlua/utils.h" +#include "unicornlua/context.hpp" +#include "unicornlua/engine.hpp" +#include "unicornlua/lua.hpp" +#include "unicornlua/unicornlua.hpp" +#include "unicornlua/utils.hpp" static int ul_unicorn_version(lua_State* L) { diff --git a/src/utils.cpp b/src/utils.cpp index e037deb0..921b12c7 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -1,7 +1,7 @@ #include -#include "unicornlua/lua.h" -#include "unicornlua/utils.h" +#include "unicornlua/lua.hpp" +#include "unicornlua/utils.hpp" int ul_crash_on_error(lua_State* L, uc_err error) { diff --git a/tests/c/compat.cpp b/tests/c/compat.cpp index 4eccfae9..29262771 100644 --- a/tests/c/compat.cpp +++ b/tests/c/compat.cpp @@ -2,9 +2,9 @@ #include #include "doctest.h" -#include "fixtures.h" -#include "unicornlua/compat.h" -#include "unicornlua/lua.h" +#include "fixtures.hpp" +#include "unicornlua/compat.hpp" +#include "unicornlua/lua.hpp" TEST_CASE_FIXTURE(LuaFixture, "[5.3 compat] lua_seti() basic") { diff --git a/tests/c/context.cpp b/tests/c/context.cpp index aba4695a..05c1f4e6 100644 --- a/tests/c/context.cpp +++ b/tests/c/context.cpp @@ -1,7 +1,7 @@ -#include "unicornlua/context.h" +#include "unicornlua/context.hpp" #include "doctest.h" -#include "fixtures.h" -#include "unicornlua/errors.h" +#include "fixtures.hpp" +#include "unicornlua/errors.hpp" TEST_CASE_FIXTURE(AutoclosingEngineFixture, "Test creating a context") { diff --git a/tests/c/engine.cpp b/tests/c/engine.cpp index b0d26c0a..437fffa3 100644 --- a/tests/c/engine.cpp +++ b/tests/c/engine.cpp @@ -1,10 +1,10 @@ #include #include "doctest.h" -#include "fixtures.h" -#include "unicornlua/context.h" -#include "unicornlua/errors.h" -#include "unicornlua/lua.h" +#include "fixtures.hpp" +#include "unicornlua/context.hpp" +#include "unicornlua/errors.hpp" +#include "unicornlua/lua.hpp" TEST_CASE_FIXTURE( EngineFixture, "UCLuaEngine::close() sets engine handle to null") diff --git a/tests/c/fixtures.cpp b/tests/c/fixtures.cpp index a68a5d5d..5e2a6e50 100644 --- a/tests/c/fixtures.cpp +++ b/tests/c/fixtures.cpp @@ -4,9 +4,9 @@ #include #include "doctest.h" -#include "fixtures.h" -#include "unicornlua/engine.h" -#include "unicornlua/lua.h" +#include "fixtures.hpp" +#include "unicornlua/engine.hpp" +#include "unicornlua/lua.hpp" LuaFixture::LuaFixture() { diff --git a/tests/c/fixtures.h b/tests/c/fixtures.hpp similarity index 70% rename from tests/c/fixtures.h rename to tests/c/fixtures.hpp index f6efd1e1..24f7351e 100644 --- a/tests/c/fixtures.h +++ b/tests/c/fixtures.hpp @@ -3,30 +3,27 @@ #include -#include "unicornlua/engine.h" -#include "unicornlua/lua.h" - +#include "unicornlua/engine.hpp" +#include "unicornlua/lua.hpp" class LuaFixture { public: LuaFixture(); virtual ~LuaFixture(); - lua_State *L; + lua_State* L; }; - class EngineFixture : public LuaFixture { public: EngineFixture(); - UCLuaEngine *uclua_engine; + UCLuaEngine* uclua_engine; }; - class AutoclosingEngineFixture : public EngineFixture { public: ~AutoclosingEngineFixture() override; }; -#endif // INCLUDE_TESTS_C_FIXTURES_H_ +#endif // INCLUDE_TESTS_C_FIXTURES_H_ diff --git a/tests/c/hooks.cpp b/tests/c/hooks.cpp index b86e206b..ccc98618 100644 --- a/tests/c/hooks.cpp +++ b/tests/c/hooks.cpp @@ -1,7 +1,7 @@ -#include "unicornlua/hooks.h" +#include "unicornlua/hooks.hpp" #include "doctest.h" -#include "fixtures.h" -#include "unicornlua/lua.h" +#include "fixtures.hpp" +#include "unicornlua/lua.hpp" TEST_CASE_FIXTURE(AutoclosingEngineFixture, "Empty Hook created as expected") { diff --git a/tests/c/registers.cpp b/tests/c/registers.cpp index 337bdc02..3e059ea6 100644 --- a/tests/c/registers.cpp +++ b/tests/c/registers.cpp @@ -6,7 +6,7 @@ #include #include "doctest.h" -#include "unicornlua/registers.h" +#include "unicornlua/registers.hpp" // Copied and pasted from registers.cpp because of linker errors static const uint8_t kFP80PositiveInfinity[] diff --git a/tests/c/utils.cpp b/tests/c/utils.cpp index 2c72cf05..81036a67 100644 --- a/tests/c/utils.cpp +++ b/tests/c/utils.cpp @@ -5,9 +5,9 @@ #include #include "doctest.h" -#include "fixtures.h" -#include "unicornlua/lua.h" -#include "unicornlua/utils.h" +#include "fixtures.hpp" +#include "unicornlua/lua.hpp" +#include "unicornlua/utils.hpp" // FIXME (dargueta): Something's wrong with this test and it's not working // right. diff --git a/tools/generate_constants.lua b/tools/generate_constants.lua index 0ad58730..762917b6 100644 --- a/tools/generate_constants.lua +++ b/tools/generate_constants.lua @@ -22,8 +22,8 @@ OUTPUT_CPP_TEMPLATE = [[ #include ! end -#include "unicornlua/lua.h" -#include "unicornlua/utils.h" +#include "unicornlua/lua.hpp" +#include "unicornlua/utils.hpp" static const struct NamedIntConst kConstants[] { ! for name, text in pairs(constants) do diff --git a/unicorn-2.2.0-1.rockspec b/unicorn-2.2.0-1.rockspec new file mode 100644 index 00000000..d9b45a91 --- /dev/null +++ b/unicorn-2.2.0-1.rockspec @@ -0,0 +1,101 @@ +rockspec_format = "3.0" +package = "unicorn" +version = "2.2.0-1" + +source = { + url = "git+ssh://git@github.com/dargueta/unicorn-lua.git", + tag = "v2.2.0" +} + +description = { + summary = "Lua bindings for the Unicorn CPU emulator.", + homepage = "https://github.com/dargueta/unicorn-lua", + license = "GPL-2" +} + +dependencies = { + "lua >= 5.1" +} + +supported_platforms = { + "linux", "macos", +} + +external_dependencies = { + platforms = { + linux = { + PTHREAD = { + library = "pthread" + }, + }, + }, + UNICORN = { + library = "unicorn", + header = "unicorn/unicorn.h" + } +} +external_dependencies.platforms.macos = external_dependencies.platforms.linux + +test_dependencies = { + "busted", +} + +test = { + type = "command", + command = "make", + flags = { + "test", + "BUSTED=$(SCRIPTS_DIR)/busted", + "CC=$(CC)", + "CURL=$(CURL)", + "CXXFLAGS=$(CFLAGS)", + "LD=$(LD)", + "LIB_EXTENSION=$(LIB_EXTENSION)", + "LUA=$(LUA)", + "LUALIB=$(LUALIB)", -- Always empty on *NIX systems + "LUA_DIR=$(LUA_DIR)", + "LUAROCKS=$(SCRIPTS_DIR)/luarocks", + "OBJ_EXTENSION=$(OBJ_EXTENSION)", + "MKDIR=$(MKDIR)", + -- The following are needed but not provided by LuaRocks + -- "LUA_INCDIR=$(LUA_INCDIR)", + -- "LUA_LIBDIR=$(LUA_LIBDIR)", + -- "UNICORN_INCDIR=$(UNICORN_INCDIR)", + -- "UNICORN_LIBDIR=$(UNICORN_LIBDIR)", + -- "PTHREAD_LIBDIR=$(PTHREAD_LIBDIR)", + }, +} + +build_dependencies = { + "penlight >=1.8.1, <2.0", +} + +build = { + type = "make", + variables = { + LIB_EXTENSION = "$(LIB_EXTENSION)", + LUA = "$(LUA)", + LUAROCKS = "$(SCRIPTS_DIR)/luarocks", + OBJ_EXTENSION = "$(OBJ_EXTENSION)", + }, + build_variables = { + CC = "$(CC)", + CURL = "$(CURL)", + CXXFLAGS = "$(CFLAGS)", + LD = "$(LD)", + LIBFLAG = "$(LIBFLAG)", + LUA_DIR = "$(LUA_DIR)", + LUA_INCDIR="$(LUA_INCDIR)", + LUA_LIBDIR = "$(LUA_LIBDIR)", + UNICORN_INCDIR = "$(UNICORN_INCDIR)", + UNICORN_LIBDIR = "$(UNICORN_LIBDIR)", + PTHREAD_LIBDIR = "$(PTHREAD_LIBDIR)", + MKDIR = "$(MKDIR)", + -- We need one of these + LUALIB = "$(LUALIB)", + LUA_LIBDIR_FILE = "$(LUA_LIBDIR_FILE)", + }, + install_variables = { + INST_LIBDIR = "$(LIBDIR)", + }, +}