From 5418ce4b3895a5886603afc5db0e6b5db4a804d4 Mon Sep 17 00:00:00 2001 From: "QCQCQC@wsl" <1220204124@zust.edu.cn> Date: Tue, 9 Dec 2025 20:08:15 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B8=85=E7=90=86=E4=B8=8D=E5=86=8D?= =?UTF-8?q?=E9=9C=80=E8=A6=81=E7=9A=84hook=5Fwrite=EF=BC=8C=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E4=BA=A4=E5=8F=89=E7=BC=96=E8=AF=91=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 78 ++++++++++++++++------ build_all.sh | 166 +++++++++++++++++++++++++++++++++++++++++++++++ src/hook_write.c | 159 --------------------------------------------- 3 files changed, 225 insertions(+), 178 deletions(-) create mode 100755 build_all.sh delete mode 100644 src/hook_write.c diff --git a/Makefile b/Makefile index fe6cbea..1bcceda 100644 --- a/Makefile +++ b/Makefile @@ -1,25 +1,39 @@ -CC = gcc +# 检测架构 +ARCH ?= $(shell uname -m) + +# 交叉编译工具链配置 +ifeq ($(ARCH),arm64) + CC = aarch64-linux-gnu-gcc + TARGET_SUFFIX = _arm64 +else ifeq ($(ARCH),aarch64) + CC = aarch64-linux-gnu-gcc + TARGET_SUFFIX = _arm64 + ARCH = arm64 +else ifeq ($(ARCH),arm) + CC = arm-linux-gnueabihf-gcc + TARGET_SUFFIX = _arm +else ifeq ($(ARCH),x86_64) + CC = gcc + TARGET_SUFFIX = _x86_64 +else + CC = gcc + TARGET_SUFFIX = _x86_64 +endif + CFLAGS = -shared -fPIC -Wall -Wextra -Werror -fno-strict-aliasing -fPIC -fno-omit-frame-pointer -fno-stack-protector -Wl,-z,relro,-z,now LDFLAGS = -ldl -HOOK_LDFLAGS = -ldl -pthread -TARGET_NAME = libbash_smart.so -HOOK_NAME = libbash_smart_hook_write.so +TARGET_NAME = libbash_smart$(TARGET_SUFFIX).so BUILD_DIR = build SRC_DIR = src TESTS_DIR = tests SRC = $(wildcard $(SRC_DIR)/*.c) -SRC := $(filter-out $(SRC_DIR)/hook_write.c, $(SRC)) # 排除 hook_write.c OBJ = $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.o,$(SRC)) TARGET = $(BUILD_DIR)/$(TARGET_NAME) -HOOK_SRC = $(SRC_DIR)/hook_write.c -HOOK_OBJ = $(BUILD_DIR)/hook_write.o -HOOK_TARGET = $(BUILD_DIR)/$(HOOK_NAME) - # 测试客户端 TEST_CLIENT = $(BUILD_DIR)/test_client TEST_CLIENT_SRC = $(TESTS_DIR)/test_client.c @@ -45,15 +59,48 @@ ifeq ($(NO_CONFIG_CHECK),1) CFLAGS += -DNO_CONFIG_CHECK endif -.PHONY: all clean debug hook rebuild pre_build test_client test_concurrent_client +.PHONY: all clean debug hook rebuild pre_build test_client test_concurrent_client arm64 arm install-cross-tools -all: pre_build $(TARGET) $(HOOK_TARGET) +all: pre_build $(TARGET) + +# 快捷方式:交叉编译到 ARM64 +arm64: + $(MAKE) ARCH=arm64 + +# 快捷方式:交叉编译到 ARM32 +arm: + $(MAKE) ARCH=arm + +# 安装交叉编译工具链 +install-cross-tools: + @echo "安装 ARM 交叉编译工具链..." + @if ! command -v aarch64-linux-gnu-gcc > /dev/null 2>&1; then \ + echo "正在安装 gcc-aarch64-linux-gnu..."; \ + sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu || \ + (echo "安装失败,尝试不更新源..." && sudo apt-get install -y --no-update gcc-aarch64-linux-gnu g++-aarch64-linux-gnu); \ + else \ + echo "aarch64-linux-gnu-gcc 已安装"; \ + fi + @if ! command -v arm-linux-gnueabihf-gcc > /dev/null 2>&1; then \ + echo "正在安装 gcc-arm-linux-gnueabihf..."; \ + sudo apt-get install -y gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf || \ + (echo "安装失败,尝试不更新源..." && sudo apt-get install -y --no-update gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf); \ + else \ + echo "arm-linux-gnueabihf-gcc 已安装"; \ + fi + @echo "交叉编译工具链安装完成!" test_client: pre_build $(TEST_CLIENT) test_concurrent_client: pre_build $(TEST_CONCURRENT_CLIENT) pre_build: + @echo "==========================================" + @echo "编译配置:" + @echo " 架构: $(ARCH)" + @echo " 编译器: $(CC)" + @echo " 目标文件: $(TARGET_NAME)" + @echo "==========================================" ifeq ($(DEBUG),1) @echo "Building with debug flags..." endif @@ -71,14 +118,7 @@ $(BUILD_DIR)/%.o: $(SRC_DIR)/%.c $(TARGET): $(OBJ) @mkdir -p $(BUILD_DIR) $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) - -$(HOOK_TARGET): $(HOOK_OBJ) - @mkdir -p $(BUILD_DIR) - $(CC) $(CFLAGS) -Wno-error=unused-result -o $@ $^ $(HOOK_LDFLAGS) - -$(HOOK_OBJ): $(HOOK_SRC) - @mkdir -p $(BUILD_DIR) - $(CC) $(CFLAGS) -Wno-error=unused-result -c $< -o $@ + @rm -f $(OBJ) $(TEST_CLIENT): $(TEST_CLIENT_SRC) $(TEST_CLIENT_DEPS) @mkdir -p $(BUILD_DIR) diff --git a/build_all.sh b/build_all.sh new file mode 100755 index 0000000..6be1639 --- /dev/null +++ b/build_all.sh @@ -0,0 +1,166 @@ +#!/bin/bash + +# 快速编译所有架构脚本 +# 用途: 一键编译 x86_64, arm64, arm 三个架构 + +set -e + +# 定义颜色 +readonly RED='\033[0;31m' +readonly GREEN='\033[0;32m' +readonly YELLOW='\033[1;33m' +readonly BLUE='\033[0;34m' +readonly NC='\033[0m' + +# 日志函数 +log_info() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +log_success() { + echo -e "${BLUE}[SUCCESS]${NC} $1" +} + +# 显示帮助信息 +show_help() { + cat << EOF +${BLUE}快速编译所有架构脚本${NC} + +用法: $0 [选项] + +选项: + -h, --help 显示此帮助信息 + --hook 启用 HOOK=1 + --no-config-check 启用 NO_CONFIG_CHECK=1 + --debug 启用 DEBUG=1 + --no-clean 跳过清理步骤 + --arch 指定编译架构 (默认: x86_64 arm64 arm) + 可以用逗号或空格分隔,例如: --arch "x86_64,arm64" + +示例: + $0 # 编译所有架构 + $0 --hook --no-config-check # 编译所有架构并启用 HOOK 和 NO_CONFIG_CHECK + $0 --debug --arch "x86_64,arm64" # 仅编译 x86_64 和 arm64,启用调试 + $0 --hook --no-config-check --debug # 编译所有架构,启用所有选项 + +EOF +} + +# 解析参数 +HOOK="" +NO_CONFIG_CHECK="" +DEBUG="" +DO_CLEAN=true +ARCHS=("x86_64" "arm64" "arm") + +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_help + exit 0 + ;; + --hook) + HOOK="HOOK=1" + shift + ;; + --no-config-check) + NO_CONFIG_CHECK="NO_CONFIG_CHECK=1" + shift + ;; + --debug) + DEBUG="DEBUG=1" + shift + ;; + --no-clean) + DO_CLEAN=false + shift + ;; + --arch) + if [[ -n "$2" && "$2" != --* ]]; then + # 支持逗号或空格分隔 + IFS=', ' read -r -a ARCHS <<< "$2" + shift 2 + else + log_error "--arch 需要参数" + exit 1 + fi + ;; + *) + log_error "未知参数: $1" + show_help + exit 1 + ;; + esac +done + +# 构建 make 参数 +MAKE_FLAGS="$HOOK $NO_CONFIG_CHECK $DEBUG" + +FAILED_ARCHS=() +SUCCESS_ARCHS=() + +echo "" +log_info "==========================================" +log_info "开始编译所有架构" +log_info "架构列表: ${ARCHS[*]}" +log_info "编译参数: $MAKE_FLAGS" +log_info "==========================================" +echo "" + +# 清理之前的编译产物 +if [ "$DO_CLEAN" = true ]; then + log_info "清理之前的编译产物..." + make clean + echo "" +fi + +# 遍历编译每个架构 +for arch in "${ARCHS[@]}"; do + log_info "----------------------------------------" + log_info "正在编译架构: $arch" + log_info "----------------------------------------" + + if make $MAKE_FLAGS ARCH=$arch; then + log_success "架构 $arch 编译成功" + SUCCESS_ARCHS+=("$arch") + else + log_error "架构 $arch 编译失败" + FAILED_ARCHS+=("$arch") + fi + + echo "" +done + +# 显示编译结果 +log_info "==========================================" +log_info "编译完成" +log_info "==========================================" +echo "" + +if [ ${#SUCCESS_ARCHS[@]} -gt 0 ]; then + log_success "成功编译的架构: ${SUCCESS_ARCHS[*]}" +fi + +if [ ${#FAILED_ARCHS[@]} -gt 0 ]; then + log_error "失败编译的架构: ${FAILED_ARCHS[*]}" +fi + +echo "" +log_info "编译产物:" +ls -lh build/*.so 2>/dev/null || log_error "没有找到编译产物" +echo "" + +# 如果有失败的架构,返回错误码 +if [ ${#FAILED_ARCHS[@]} -gt 0 ]; then + exit 1 +fi + +log_success "所有架构编译完成!" +echo "" +log_info "本次编译使用的参数:" +log_info " 架构: ${ARCHS[*]}" +log_info " 编译选项: ${MAKE_FLAGS:-无}" diff --git a/src/hook_write.c b/src/hook_write.c deleted file mode 100644 index 82be205..0000000 --- a/src/hook_write.c +++ /dev/null @@ -1,159 +0,0 @@ -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include - -#include "debug.h" -#include "exec_hook.h" - -static int log_fd = -1; - -// 原始函数指针 -static ssize_t (*original_write)(int, const void *, size_t) = NULL; -static ssize_t (*orig_writev)(int, const struct iovec *, int) = NULL; -static size_t (*orig_fwrite)(const void *, size_t, size_t, FILE *) = NULL; -static int (*orig_fflush)(FILE *) = NULL; -static int (*orig_puts)(const char *) = NULL; -static int (*orig_printf)(const char *, ...) = NULL; -static int (*orig_vprintf)(const char *, va_list) = NULL; -static int (*orig_vfprintf)(FILE *, const char *, va_list) = NULL; - -void init_hook() { - DEBUG_LOG("Initializing write hooks..."); - - original_write = dlsym(RTLD_NEXT, "write"); - orig_writev = dlsym(RTLD_NEXT, "writev"); - orig_fwrite = dlsym(RTLD_NEXT, "fwrite"); - orig_fflush = dlsym(RTLD_NEXT, "fflush"); - orig_puts = dlsym(RTLD_NEXT, "puts"); - orig_printf = dlsym(RTLD_NEXT, "printf"); - orig_vprintf = dlsym(RTLD_NEXT, "vprintf"); - orig_vfprintf = dlsym(RTLD_NEXT, "vfprintf"); - - log_fd = open(LOG_OUT_FILE, O_WRONLY | O_CREAT | O_APPEND, 0644); - if (log_fd == -1) { - perror("Failed to open log file"); - } -} - -ssize_t write(int fd, const void *buf, size_t count) { - DEBUG_LOG("Intercepted write to fd %d", fd); - ssize_t result = original_write(fd, buf, count); - - if (log_fd != -1 && (fd == STDOUT_FILENO || fd == STDERR_FILENO) && fd != log_fd) { - original_write(log_fd, buf, count); - } - - return result; -} - -ssize_t writev(int fd, const struct iovec *iov, int iovcnt) { - DEBUG_LOG("Intercepted writev to fd %d", fd); - ssize_t result = orig_writev(fd, iov, iovcnt); - - if (log_fd != -1 && (fd == STDOUT_FILENO || fd == STDERR_FILENO) && fd != log_fd) { - for (int i = 0; i < iovcnt; ++i) { - write(log_fd, iov[i].iov_base, iov[i].iov_len); - } - } - - return result; -} - -size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) { - DEBUG_LOG("Intercepted fwrite to stream %p", stream); - size_t result = orig_fwrite(ptr, size, nmemb, stream); - int fd = fileno(stream); - if (log_fd != -1 && (fd == STDOUT_FILENO || fd == STDERR_FILENO)) { - write(log_fd, ptr, size * nmemb); - } - return result; -} - -int puts(const char *s) { - DEBUG_LOG("Intercepted puts: %s", s); - int result = orig_puts(s); - if (log_fd != -1) { - write(log_fd, s, strlen(s)); - write(log_fd, "\n", 1); - } - return result; -} - -int printf(const char *format, ...) { - DEBUG_LOG("Intercepted printf: %s", format); - va_list args; - va_start(args, format); - int result = orig_vprintf(format, args); - va_end(args); - - // 再次获取 args 写入日志 - va_start(args, format); - if (log_fd != -1) { - char buffer[4096]; - int len = vsnprintf(buffer, sizeof(buffer), format, args); - if (len > 0) { - write(log_fd, buffer, len); - } - } - va_end(args); - return result; -} - -int vprintf(const char *format, va_list args) { - DEBUG_LOG("Intercepted vprintf: %s", format); - int result = orig_vprintf(format, args); - if (log_fd != -1) { - char buffer[4096]; - va_list args_copy; - va_copy(args_copy, args); - int len = vsnprintf(buffer, sizeof(buffer), format, args_copy); - va_end(args_copy); - if (len > 0) { - write(log_fd, buffer, len); - } - } - return result; -} - -int vfprintf(FILE *stream, const char *format, va_list args) { - DEBUG_LOG("Intercepted vfprintf to stream %p: %s", stream, format); - int result = orig_vfprintf(stream, format, args); - - int fd = fileno(stream); - if (log_fd != -1 && (fd == STDOUT_FILENO || fd == STDERR_FILENO)) { - va_list args_copy; - va_copy(args_copy, args); - char buffer[4096]; - int len = vsnprintf(buffer, sizeof(buffer), format, args_copy); - va_end(args_copy); - if (len > 0) { - write(log_fd, buffer, len); - } - } - - return result; -} - -int fflush(FILE *stream) { - DEBUG_LOG("Intercepted fflush to stream %p", stream); - return orig_fflush(stream); -} - -__attribute__((constructor)) void init() { - DEBUG_LOG("Write hook library loaded."); - init_hook(); -} - -__attribute__((destructor)) void cleanup() { - if (log_fd != -1) { - close(log_fd); - log_fd = -1; - } - DEBUG_LOG("Write hook library unloaded."); -}