Skip to content

Commit

Permalink
UnitTestFrameworkPkg/Library/SubhookLib: Removed subhook from submodu…
Browse files Browse the repository at this point in the history
…les.
  • Loading branch information
Mikhail Krichanov committed Nov 4, 2024
1 parent 07cb35d commit c798054
Show file tree
Hide file tree
Showing 26 changed files with 1,863 additions and 6 deletions.
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@
[submodule "UnitTestFrameworkPkg/Library/GoogleTestLib/googletest"]
path = UnitTestFrameworkPkg/Library/GoogleTestLib/googletest
url = https://github.com/google/googletest.git
[submodule "UnitTestFrameworkPkg/Library/SubhookLib/subhook"]
path = UnitTestFrameworkPkg/Library/SubhookLib/subhook
url = https://github.com/Zeex/subhook.git
[submodule "MdePkg/Library/BaseFdtLib/libfdt"]
path = MdePkg/Library/BaseFdtLib/libfdt
url = https://github.com/devicetree-org/pylibfdt.git
Expand Down
2 changes: 0 additions & 2 deletions .pytool/CISettings.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,6 @@ def GetRequiredSubmodules(self):
"BaseTools/Source/C/BrotliCompress/brotli", False))
rs.append(RequiredSubmodule(
"RedfishPkg/Library/JsonLib/jansson", False))
rs.append(RequiredSubmodule(
"UnitTestFrameworkPkg/Library/SubhookLib/subhook", False))
rs.append(RequiredSubmodule(
"MdePkg/Library/BaseFdtLib/libfdt", False))
rs.append(RequiredSubmodule(
Expand Down
1 change: 0 additions & 1 deletion UnitTestFrameworkPkg/Library/SubhookLib/subhook
Submodule subhook deleted from 83d4e1
10 changes: 10 additions & 0 deletions UnitTestFrameworkPkg/Library/SubhookLib/subhook/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# EditorConfig is awesome: http://EditorConfig.org

root = true

[*]
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
30 changes: 30 additions & 0 deletions UnitTestFrameworkPkg/Library/SubhookLib/subhook/.travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
language: c

os:
- linux
- osx
- freebsd
env:
global:
- CTEST_OUTPUT_ON_FAILURE=ON
matrix:
- ARCH=x86
- ARCH=x86_64
addons:
apt:
packages:
- gcc
- g++
- gcc-multilib
- g++-multilib
- cmake
- yasm
before_install:
- if [ $TRAVIS_OS_NAME == osx ]; then brew install yasm; fi
- if [ $TRAVIS_OS_NAME == freebsd ]; then sudo pkg install -y yasm; fi

before_script:
- cmake . -DSUBHOOK_FORCE_32BIT=`([ $ARCH = x86 ] && echo 'ON') || echo 'OFF'`
script:
- make
- make test
109 changes: 109 additions & 0 deletions UnitTestFrameworkPkg/Library/SubhookLib/subhook/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
cmake_minimum_required(VERSION 3.10)

project(subhook VERSION 0.8.2 LANGUAGES C)

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

include(GNUInstallDirs)

macro(subhook_add_option_var name type default_value description)
set(${name}_DEFAULT ${default_value})
if(DEFINED ${name})
set(${name}_DEFAULT ${${name}})
endif()
set(${name} ${${name}_DEFAULT} CACHE ${type} ${description})
endmacro()

subhook_add_option_var(SUBHOOK_STATIC BOOL OFF "Build as a static library")
subhook_add_option_var(SUBHOOK_INSTALL
BOOL ON "Enable installation and packaging of targets/files with CPack")
subhook_add_option_var(SUBHOOK_TESTS BOOL ON "Enable tests")
subhook_add_option_var(SUBHOOK_FORCE_32BIT
BOOL OFF "Configure for compiling 32-bit binaries (on 64-bit systems)")

set(SUBHOOK_HEADERS subhook.h)
set(SUBHOOK_SOURCES subhook.c subhook_private.h subhook_x86.c)
if(WIN32)
list(APPEND SUBHOOK_SOURCES subhook_windows.c)
elseif(UNIX)
list(APPEND SUBHOOK_SOURCES subhook_unix.c)
endif()

if(SUBHOOK_STATIC)
add_library(subhook STATIC ${SUBHOOK_HEADERS} ${SUBHOOK_SOURCES})
target_compile_definitions(subhook PUBLIC SUBHOOK_STATIC)
else()
add_library(subhook SHARED ${SUBHOOK_HEADERS} ${SUBHOOK_SOURCES})
endif()

add_library(subhook::subhook ALIAS subhook)

target_compile_definitions(subhook PUBLIC
SUBHOOK_IMPLEMENTATION
SUBHOOK_SEPARATE_SOURCE_FILES
)
target_include_directories(subhook PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)

if(CMAKE_COMPILER_ID MATCHES GNU OR CMAKE_C_COMPILER_ID MATCHES Clang)
target_compile_options(subhook PRIVATE "-Wall -Wextra")
endif()

if(SUBHOOK_FORCE_32BIT)
if(APPLE)
set_target_properties(subhook PROPERTIES OSX_ARCHITECTURES i386)
endif()
if(UNIX)
target_compile_options(subhook PRIVATE "-m32")
target_link_options(subhook PRIVATE "-m32")
endif()
endif()

set_property(GLOBAL PROPERTY USE_FOLDERS ON)

if(SUBHOOK_INSTALL)
include(CMakePackageConfigHelpers)

install(TARGETS subhook EXPORT ${PROJECT_NAME}Targets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(FILES ${SUBHOOK_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

set(config_file ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake)
set(version_file ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake)
set(config_install_destination lib/cmake/${PROJECT_NAME})

configure_package_config_file(
${CMAKE_CURRENT_SOURCE_DIR}/cmake/Config.cmake.in
${config_file}
INSTALL_DESTINATION ${config_install_destination}
)

write_basic_package_version_file(
${version_file}
COMPATIBILITY SameMajorVersion
)

install(FILES ${config_file} ${version_file} DESTINATION ${config_install_destination})
install(
EXPORT ${PROJECT_NAME}Targets
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${config_install_destination}
)
endif()

set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})

include(CPack)
include(CTest)

if(BUILD_TESTING AND SUBHOOK_TESTS)
enable_testing()
add_subdirectory(tests)
endif()
23 changes: 23 additions & 0 deletions UnitTestFrameworkPkg/Library/SubhookLib/subhook/LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Copyright (c) 2012-2018 Zeex
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
165 changes: 165 additions & 0 deletions UnitTestFrameworkPkg/Library/SubhookLib/subhook/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
[![Build Status][build_status]][build]
[![Build Status - Windows][build_status_win]][build_win]

SubHook is a super-simple hooking library for C and C++ that works on Windows,
Linux and macOS. It supports x86 only (32-bit and 64-bit).

Installation
------------

Easy method:

1. Copy the source and header files to your project and include
[`subhook.c`](subhook.c) in your build.
2. On Windows only: Define `SUBHOOK_STATIC` before including `subhook.h`.

With CMake:

1. Copy the subhook repo to your project tree.
2. Call `add_subdirectory(path/to/subhook)` in your CMakeLists.txt.
3. Optional: configure how the library is built by setting these varaible prior
to `add_subdirectory(...)`:

* `SUBHOOK_STATIC` - Build as static library (`OFF` by default)
* `SUBHOOK_INSTALL` - Enable installation and packaging of targets/files
with CPack (`OFF` by default)
* `SUBHOOK_TESTS` - Enable tests (`ON` by default)
* `SUBHOOK_FORCE_32BIT` - Configure for compiling 32-bit binaries on 64-bit
systems (default is `OFF`)

Use of CMake is not mandatory, the library can be built without it (no extra
build configuration is required).

Examples
--------

In the following examples `foo` is some function or a function pointer that
takes a single argument of type `int` and uses the same calling convention
as `my_foo` (depends on compiler).

### Basic usage

```c
#include <stdio.h>
#include <subhook.h>

subhook_t foo_hook;

void my_foo(int x) {
/* Remove the hook so that you can call the original function. */
subhook_remove(foo_hook);

printf("foo(%d) called\n", x);
foo(x);

/* Install the hook back to intercept further calls. */
subhook_install(foo_hook);
}

int main() {
/* Create a hook that will redirect all foo() calls to to my_foo(). */
foo_hook = subhook_new((void *)foo, (void *)my_foo, 0);

/* Install it. */
subhook_install(foo_hook);

foo(123);

/* Remove the hook and free memory when you're done. */
subhook_remove(foo_hook);
subhook_free(foo_hook);
}
```
### Trampolines
Using trampolines allows you to jump to the original code without removing
and re-installing hooks every time your function gets called.
```c
typedef void (*foo_func)(int x);
void my_foo(int x) {
printf("foo(%d) called\n", x);
/* Call foo() via trampoline. */
((foo_func)subhook_get_trampoline(foo_hook))(x);
}
int main() {
/* Same code as in the previous example. */
}
```

Please note that subhook has a very simple length disassmebler engine (LDE)
that works only with most common prologue instructions like push, mov, call,
etc. When it encounters an unknown instruction subhook_get_trampoline() will
return NULL. You can delegate instruction decoding to a custom disassembler
of your choice via `subhook_set_disasm_handler()`.

### C++

```c++
#include <iostream>
#include <subhook.h>

subhook::Hook foo_hook;
subhook::Hook foo_hook_tr;

typedef void (*foo_func)(int x);

void my_foo(int x) {
// ScopedHookRemove removes the specified hook and automatically re-installs
// it when the object goes out of scope (thanks to C++ destructors).
subhook::ScopedHookRemove remove(&foo_hook);

std::cout << "foo(" << x << ") called" << std::endl;
foo(x + 1);
}

void my_foo_tr(int x) {
std::cout << "foo(" << x << ") called" << std::endl;

// Call the original function via trampoline.
((foo_func)foo_hook_tr.GetTrampoline())(x + 1);
}

int main() {
foo_hook.Install((void *)foo, (void *)my_foo);
foo_hook_tr.Install((void *)foo, (void *)my_foo_tr);
}
```
Known issues
------------
* `subhook_get_trampoline()` may return NULL because only a small subset of
x86 instructions is supported by the disassembler in this library (just
common prologue instructions). As a workaround you can plug in a more
advanced instruction length decoder using `subhook_set_disasm_handler()`.
* If a target function (the function you are hooking) is less than N bytes
in length, for example if it's a short 2-byte jump to a nearby location
(sometimes compilers generate code like this), then you will not be able
to hook it.
N is 5 by default: 1 byte for jmp opcode + 4 bytes for offset. But if you
enable the use of 64-bit offsets in 64-bit mode N becomes 14 (see the
definition of `subhook_jmp64`).
* Some systems protect executable code form being modified at runtime, which
will not allow you to install hooks, or don't allow to mark heap-allocated
memory as executable, which prevents the use of trampolines.
For example, on Fedora you can have such problems because of SELinux (though
you can disable it or exclude your files).
License
-------
Licensed under the 2-clause BSD license.
[build]: https://travis-ci.org/Zeex/subhook
[build_status]: https://travis-ci.org/Zeex/subhook.svg?branch=master
[build_win]: https://ci.appveyor.com/project/Zeex/subhook/branch/master
[build_status_win]: https://ci.appveyor.com/api/projects/status/q5sp0p8ahuqfh8e4/branch/master?svg=true
20 changes: 20 additions & 0 deletions UnitTestFrameworkPkg/Library/SubhookLib/subhook/appveyor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
version: '{build}'

platform:
- x86
- x64
configuration:
- Release
environment:
CTEST_OUTPUT_ON_FAILURE: ON

install:
- choco install -y yasm
before_build:
- if %PLATFORM% == x86 set BUILD_ARCH=Win32
- if %PLATFORM% == x64 set BUILD_ARCH=x64
- cmake . -A %BUILD_ARCH%
build_script:
- cmake --build . --config %CONFIGURATION%
test_script:
- ctest --build-config %CONFIGURATION%
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@PACKAGE_INIT@

include("${CMAKE_CURRENT_LIST_DIR}/@[email protected]")
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
include(FindPackageHandleStandardArgs)

find_file(YASM_EXECUTABLE NAMES yasm yasm.exe)
mark_as_advanced(YASM_EXECUTABLE)

find_package_handle_standard_args(Yasm
FOUND_VAR YASM_FOUND
REQUIRED_VARS YASM_EXECUTABLE
)
Loading

0 comments on commit c798054

Please sign in to comment.