From aff3ac4c6da830f24b7e79f0ec0688cecaf2fa2f Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 1 Jun 2026 21:45:16 +0000 Subject: [PATCH 001/156] Re-enable the dynamorio kernel module --- core/kernel_linux/modules/Makefile | 117 ++++++++++++++--------------- 1 file changed, 57 insertions(+), 60 deletions(-) diff --git a/core/kernel_linux/modules/Makefile b/core/kernel_linux/modules/Makefile index 6bbf54d97..d67686373 100644 --- a/core/kernel_linux/modules/Makefile +++ b/core/kernel_linux/modules/Makefile @@ -18,66 +18,63 @@ dynamorio_controller-objs :=\ ../../kernel_linux/simple_tests/repstr.o\ ../../kernel_linux/simple_tests.o -################################################################################ -## TODO i#20: Re-enable this module once the previous module has been ported. -## obj-m += dynamorio.o -## dynamorio-objs :=\ -## ../../exports.o\ -## ../../buildmark.o\ -## ../../config.o\ -## ../../dispatch.o\ -## ../../dynamo.o\ -## ../../emit.o\ -## ../../fcache.o\ -## ../../fragment.o\ -## ../../hashtable.o\ -## ../../heap.o\ -## ../../hotpatch.o\ -## ../../instrlist.o\ -## ../../io.o\ -## ../../link.o\ -## ../../loader_shared.o\ -## ../../moduledb.o\ -## ../../module_list.o\ -## ../../monitor.o\ -## ../../nudge.o\ -## ../../options.o\ -## ../../perfctr.o\ -## ../../perscache.o\ -## ../../rct.o\ -## ../../stats.o\ -## ../../synch.o\ -## ../../unit-rct.o\ -## ../../utils.o\ -## ../../barrier.o\ -## ../../vmareas.o\ -## ../../x86/arch.o\ -## ../../x86/decode.o\ -## ../../x86/decode_fast.o\ -## ../../x86/decode_table.o\ -## ../../x86/disassemble.o\ -## ../../x86/emit_utils.o\ -## ../../x86/encode.o\ -## ../../x86/instr.o\ -## ../../x86/instrument.o\ -## ../../x86/interp.o\ -## ../../x86/loadtoconst.o\ -## ../../x86/mangle.o\ -## ../../x86/optimize.o\ -## ../../x86/proc.o\ -## ../../x86/retcheck.o\ -## ../../x86/sideline.o\ -## ../../x86/steal_reg.o\ -## ../../x86/x86_code.o\ -## ../../x86/asm_defines.o\ -## ../../x86/x86.o\ -## ../../kernel_linux/os.o\ -## ../../kernel_linux/hypercall_guest.o\ -## ../../kernel_linux/page_table.o\ -## ../../kernel_linux/kernel_interface.o\ -## ../../kernel_linux/dynamorio_module_interface.o\ -## ../../kernel_linux/dynamorio_module.o -################################################################################ +obj-m += dynamorio.o +dynamorio-objs :=\ +../../exports.o\ +../../buildmark.o\ +../../config.o\ +../../dispatch.o\ +../../dynamo.o\ +../../emit.o\ +../../fcache.o\ +../../fragment.o\ +../../hashtable.o\ +../../heap.o\ +../../hotpatch.o\ +../../instrlist.o\ +../../io.o\ +../../link.o\ +../../loader_shared.o\ +../../moduledb.o\ +../../module_list.o\ +../../monitor.o\ +../../nudge.o\ +../../options.o\ +../../perfctr.o\ +../../perscache.o\ +../../rct.o\ +../../stats.o\ +../../synch.o\ +../../unit-rct.o\ +../../utils.o\ +../../barrier.o\ +../../vmareas.o\ +../../x86/arch.o\ +../../x86/decode.o\ +../../x86/decode_fast.o\ +../../x86/decode_table.o\ +../../x86/disassemble.o\ +../../x86/emit_utils.o\ +../../x86/encode.o\ +../../x86/instr.o\ +../../x86/instrument.o\ +../../x86/interp.o\ +../../x86/loadtoconst.o\ +../../x86/mangle.o\ +../../x86/optimize.o\ +../../x86/proc.o\ +../../x86/retcheck.o\ +../../x86/sideline.o\ +../../x86/steal_reg.o\ +../../x86/x86_code.o\ +../../x86/asm_defines.o\ +../../x86/x86.o\ +../../kernel_linux/os.o\ +../../kernel_linux/hypercall_guest.o\ +../../kernel_linux/page_table.o\ +../../kernel_linux/kernel_interface.o\ +../../kernel_linux/dynamorio_module_interface.o\ +../../kernel_linux/dynamorio_module.o ################################################################################ ## TODO i#20: Re-enable this module once the previous modules have been ported. From e0a8e7314f5ac4549915b62c34a3e40cb1b45611 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 1 Jun 2026 22:21:22 +0000 Subject: [PATCH 002/156] Fix issues in globals_api.h --- core/lib/globals_api.h | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/core/lib/globals_api.h b/core/lib/globals_api.h index 799cce2b4..13bd2d6de 100644 --- a/core/lib/globals_api.h +++ b/core/lib/globals_api.h @@ -52,10 +52,17 @@ # include # include #else -# include -# include +# ifndef LINUX_KERNEL +# include +# include +# endif +#endif + +#ifdef LINUX_KERNEL +# include /* for varargs */ +#else +# include /* for varargs */ #endif -#include /* for varargs */ #ifndef DYNAMORIO_INTERNAL /* A client's target operating system and architecture must be specified. */ @@ -105,7 +112,7 @@ * behave properly. It indents the guard. There seems to be no workaround. */ /* clang-format off */ -# ifndef __cplusplus +# if !defined(__cplusplus) && !defined(LINUX_KERNEL) # ifdef WINDOWS # define inline __inline # else @@ -129,7 +136,11 @@ typedef char bool; # endif # ifdef UNIX -# include /* for pid_t (non-glibc, e.g. musl) */ +# ifdef LINUX_KERNEL +# include +# else +# include /* for pid_t (non-glibc, e.g. musl) */ +# endif # endif # ifdef WINDOWS /* allow nameless struct/union */ @@ -209,7 +220,7 @@ typedef signed char sbyte; #endif typedef byte *app_pc; -typedef void (*generic_func_t)(); +typedef void (*generic_func_t)(void); #ifdef DR_DEFINE_FOR_uint64 # undef DR_DO_NOT_DEFINE_uint64 From e0b20aca217a6ef50c6a2d5b4df98bbdd9e596bf Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 1 Jun 2026 23:14:30 +0000 Subject: [PATCH 003/156] Fix includes in globals_shared.h --- core/lib/globals_shared.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/core/lib/globals_shared.h b/core/lib/globals_shared.h index c048249e7..29e39a5dc 100644 --- a/core/lib/globals_shared.h +++ b/core/lib/globals_shared.h @@ -76,9 +76,18 @@ #include "globals_api.h" // IWYU pragma: export -#include /* for USHRT_MAX */ +#ifdef LINUX_KERNEL +# include /* for USHRT_MAX */ +#else +# include /* for USHRT_MAX */ +#endif + #ifdef UNIX -# include +# ifdef LINUX_KERNEL +# include +# else +# include +# endif #endif #include "c_defines.h" // IWYU pragma: export From 8cae6ff1a4e40a86dc5a512c93e0803412806127 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 1 Jun 2026 23:15:00 +0000 Subject: [PATCH 004/156] Define DYNAMORIO_INTERNAL when building drk --- core/drk.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/drk.mk b/core/drk.mk index fc14357bc..7608dbc68 100644 --- a/core/drk.mk +++ b/core/drk.mk @@ -10,7 +10,7 @@ API_INCLUDE_DIR ?= lib/include .PHONY: test DR_CORE_DIR := $(shell pwd) -DR_INCLUDE_FLAGS := -DDR_REG_ENUM_COMPATIBILITY -DLINUX_KERNEL\ +DR_INCLUDE_FLAGS := -DDR_REG_ENUM_COMPATIBILITY -DLINUX_KERNEL -DDYNAMORIO_INTERNAL\ -I$(DR_CORE_DIR)/../build\ -I$(DR_CORE_DIR)/$(API_INCLUDE_DIR)\ -I$(DR_CORE_DIR)\ From 2a84c2d1ef2c59ed1a61fa340802c0ba4562b0e7 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 1 Jun 2026 23:15:28 +0000 Subject: [PATCH 005/156] Fix includes in globals.h --- core/globals.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/core/globals.h b/core/globals.h index 60446e069..e8e9d0df6 100644 --- a/core/globals.h +++ b/core/globals.h @@ -154,8 +154,10 @@ #define INLINE_ONCE inline -#include -#include +#ifndef LINUX_KERNEL +# include +# include +#endif /* N.B.: some of these typedefs and defines are duplicated in * lib/globals_shared.h! @@ -186,7 +188,7 @@ typedef HANDLE file_t; # if defined(MACOS) || defined(ANDROID) typedef unsigned long ulong; # endif -# include /* for wait */ +# include "types_wrapper.h" /* for wait */ # define DIRSEP '/' # define ALT_DIRSEP DIRSEP #endif From d75c2c33fc7afc9c8dbca6f5ba62500322e3dcd6 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 2 Jun 2026 00:04:33 +0000 Subject: [PATCH 006/156] Add explicit void to function prototypes --- core/heap.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/heap.h b/core/heap.h index e072f4d3d..c80c2f430 100644 --- a/core/heap.h +++ b/core/heap.h @@ -146,21 +146,21 @@ vmm_heap_fork_init(dcontext_t *dcontext); void print_vmm_heap_data(file_t outf); byte * -vmcode_get_start(); +vmcode_get_start(void); byte * -vmcode_get_end(); +vmcode_get_end(void); void iterate_vmm_regions(void (*cb)(byte *region_start, byte *region_end, void *user_data), void *user_data); byte * -vmcode_unreachable_pc(); +vmcode_unreachable_pc(void); byte * vmcode_get_writable_addr(byte *exec_addr); byte * vmcode_get_executable_addr(byte *write_addr); void -vmm_heap_handle_pending_low_on_memory_event_trigger(); +vmm_heap_handle_pending_low_on_memory_event_trigger(void); bool heap_check_option_compatibility(void); From 9aff9669e3f7c6f478c597bbfc24dc99df8e058c Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 2 Jun 2026 00:04:59 +0000 Subject: [PATCH 007/156] Remove redundant function type cast --- ext/drsyms/drsyms_unix_frontend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/drsyms/drsyms_unix_frontend.c b/ext/drsyms/drsyms_unix_frontend.c index f67cd0728..ac517abad 100644 --- a/ext/drsyms/drsyms_unix_frontend.c +++ b/ext/drsyms/drsyms_unix_frontend.c @@ -207,7 +207,7 @@ drsym_init(int shmid_in) } else { hashtable_init_ex(&modtable, MODTABLE_HASH_BITS, HASH_STRING, true /*strdup*/, false /*!synch: using symbol_lock*/, - (generic_func_t)drsym_unix_unload, NULL, NULL); + drsym_unix_unload, NULL, NULL); } return DRSYM_SUCCESS; } From d29bfeb514f19deaae0a993e2172f25998aefff9 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 2 Jun 2026 00:16:02 +0000 Subject: [PATCH 008/156] Use basename instead of absolute path in comment `make style_reports` complains when a line is too long (over 90 characters). Changing from absolute path to base name in this "generated by" comment resolves this issue. --- core/exports.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/exports.py b/core/exports.py index cf3d3c2d3..44aea4088 100755 --- a/core/exports.py +++ b/core/exports.py @@ -85,7 +85,7 @@ def main(): functions.difference_update(excluded_functions()) functions.update(extra_symbols()) print( - f"/* This file was automatically generated by {os.path.abspath(sys.argv[0])}. */" + f"/* This file was automatically generated by {os.path.basename(sys.argv[0])}. */" ) print("#include ") for function in functions: From 447361600c785d8ddff650461c1df6fd4a371054 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 2 Jun 2026 00:24:37 +0000 Subject: [PATCH 009/156] Build DynamoRIO in drk CI to generate `event_strings.h` --- .github/workflows/ci-drk.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci-drk.yml b/.github/workflows/ci-drk.yml index 15aa21da8..b3b8cfd67 100644 --- a/.github/workflows/ci-drk.yml +++ b/.github/workflows/ci-drk.yml @@ -35,6 +35,7 @@ jobs: mkdir -p build cd build cmake .. + $MAKE_CMD - name: Build drk # TODO i#10: Convert to cmake. From 05f006c792192ae790afe6427fe9fa015dd9cbed Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 2 Jun 2026 00:26:43 +0000 Subject: [PATCH 010/156] Add explicit void to function prototypes --- core/options.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/options.h b/core/options.h index 90d65abc4..594ffb65b 100644 --- a/core/options.h +++ b/core/options.h @@ -235,12 +235,12 @@ extern read_write_lock_t options_lock; /* full access to string requires read lock */ static inline void -string_option_read_lock() +string_option_read_lock(void) { d_r_read_lock(&options_lock); } static inline void -string_option_read_unlock() +string_option_read_unlock(void) { d_r_read_unlock(&options_lock); } From 4204aa42cdcb206ab418c0b47b464860b98f7173 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 2 Jun 2026 00:27:21 +0000 Subject: [PATCH 011/156] Remove unnecessary LINUX_KERNEL definition in exports.py --- core/exports.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/exports.py b/core/exports.py index 44aea4088..cafc4fadf 100755 --- a/core/exports.py +++ b/core/exports.py @@ -73,7 +73,7 @@ def main(): if "aarch64" in path or "arm" in path: continue code = check_open( - f"cpp -DX86_64 -DLINUX -DLINUX_KERNEL -Ilib/include -include dr_api.h {path}".split() + f"cpp -DX86_64 -DLINUX -Ilib/include -include dr_api.h {path}".split() ) for match in re.findall( r"^\s*(?:[a-zA-Z0-9_]+\s+)*([a-zA-Z0-9_]+)\(", code, re.MULTILINE From 224770293dbdf3ee7c1c6fcb957e179ff52b69ad Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 2 Jun 2026 00:48:36 +0000 Subject: [PATCH 012/156] Fix includes in drlibc.h for kernel builds --- core/drlibc/drlibc.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/core/drlibc/drlibc.h b/core/drlibc/drlibc.h index 51e46df98..abd0f7d02 100644 --- a/core/drlibc/drlibc.h +++ b/core/drlibc/drlibc.h @@ -41,12 +41,14 @@ #define _DR_LIBC_H_ #ifdef UNIX +# ifndef LINUX_KERNEL /* _LARGEFILE64_SOURCE should make libc struct match kernel. */ -# ifndef _LARGEFILE64_SOURCE -# define _LARGEFILE64_SOURCE +# ifndef _LARGEFILE64_SOURCE +# define _LARGEFILE64_SOURCE +# endif +# include +# include # endif -# include -# include #endif #if defined(MACOS) && defined(AARCH64) From 39cda658a652405a3fabff3beaedab137242b63b Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 2 Jun 2026 01:07:04 +0000 Subject: [PATCH 013/156] Add explicit void to function prototypes --- core/os_shared.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/os_shared.h b/core/os_shared.h index 381ce9dce..ea6b80d9b 100644 --- a/core/os_shared.h +++ b/core/os_shared.h @@ -302,7 +302,7 @@ char * get_application_name(void); int -num_app_args(); +num_app_args(void); int get_app_args(DR_PARAM_OUT dr_app_arg_t *args_array, int args_count); const char * @@ -418,7 +418,7 @@ os_syslog(syslog_event_type_t priority, uint message_id, uint substitutions_num, * XXX: we're duplicating these types above as dr_auxlib* */ typedef void *shlib_handle_t; -typedef void (*shlib_routine_ptr_t)(); +typedef void (*shlib_routine_ptr_t)(void); shlib_handle_t load_shared_library(const char *name, bool reachable); @@ -1010,7 +1010,7 @@ query_time_millis(void); /* microseconds since 1601 */ uint64 -query_time_micros(); +query_time_micros(void); /* gives a good but not necessarily crypto-strength random seed */ uint From 65a22e35a6a195056f848abaa04c982b75df9431 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 2 Jun 2026 01:18:29 +0000 Subject: [PATCH 014/156] Add explicit void to function prototypes --- core/globals.h | 4 ++-- core/os_api.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/globals.h b/core/globals.h index e8e9d0df6..f809c0af8 100644 --- a/core/globals.h +++ b/core/globals.h @@ -535,9 +535,9 @@ DYNAMORIO_EXPORT int dynamorio_app_init(void); /* dynamorio_app_init() can be called in two parts: */ void -dynamorio_app_init_part_one_options(); +dynamorio_app_init_part_one_options(void); int -dynamorio_app_init_part_two_finalize(); +dynamorio_app_init_part_two_finalize(void); int dynamorio_app_exit(void); dcontext_t * diff --git a/core/os_api.h b/core/os_api.h index ec349274c..c46f110fd 100644 --- a/core/os_api.h +++ b/core/os_api.h @@ -396,7 +396,7 @@ dr_convert_pid_to_handle(process_id_t pid); */ typedef void *dr_auxlib_handle_t; /** An exported routine in a loaded client auxiliary library. */ -typedef void (*dr_auxlib_routine_ptr_t)(); +typedef void (*dr_auxlib_routine_ptr_t)(void); #if defined(WINDOWS) && !defined(X64) /** * A handle to a loaded 64-bit client auxiliary library. This is a different From 2c6025affbc9cad989e26e5ac9c426a9dcc06321 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 2 Jun 2026 01:24:45 +0000 Subject: [PATCH 015/156] Pull in definition of tls_offset_t from drk --- core/os_shared.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/core/os_shared.h b/core/os_shared.h index ea6b80d9b..c067cea91 100644 --- a/core/os_shared.h +++ b/core/os_shared.h @@ -249,9 +249,15 @@ get_thread_private_dcontext(void); void set_thread_private_dcontext(dcontext_t *dcontext); +#ifdef LINUX_KERNEL +typedef uint tls_offset_t; +#else +typedef ushort tls_offset_t; +#endif + /* converts a local_state_t offset to a segment offset */ -ushort -os_tls_offset(ushort tls_offs); +tls_offset_t +os_tls_offset(tls_offset_t tls_offs); ushort os_local_state_offset(ushort seg_offs); From c1e97b36ec4e1809c61006c179777228ad80e424 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 2 Jun 2026 01:29:55 +0000 Subject: [PATCH 016/156] Build drk before downloading kernel source so that style check doesn't complain about tabs in kernel docs --- .github/workflows/ci-drk.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci-drk.yml b/.github/workflows/ci-drk.yml index b3b8cfd67..78f97901d 100644 --- a/.github/workflows/ci-drk.yml +++ b/.github/workflows/ci-drk.yml @@ -17,6 +17,13 @@ jobs: sudo apt install -y doxygen vera++ libelf-dev scons cmake g++-multilib echo "MAKE_CMD=make -j$(nproc)" >> $GITHUB_ENV + - name: Generate DynamoRIO headers via CMake + run: | + mkdir -p build + cd build + cmake .. + $MAKE_CMD + - name: Download and extract kernel source run: | VERSION="6.6.130" @@ -30,13 +37,6 @@ jobs: make defconfig $MAKE_CMD modules_prepare - - name: Generate DynamoRIO headers via CMake - run: | - mkdir -p build - cd build - cmake .. - $MAKE_CMD - - name: Build drk # TODO i#10: Convert to cmake. run: cd core && $MAKE_CMD -f drk.mk KERNELDIR=$GITHUB_WORKSPACE/$KERNEL_DIR From e6eac864e7ddaaa8dda520a40faef0322bb6edd7 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 2 Jun 2026 01:40:24 +0000 Subject: [PATCH 017/156] Re-format code with clang-format --- core/globals.h | 2 +- core/lib/globals_shared.h | 6 +++--- ext/drsyms/drsyms_unix_frontend.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/globals.h b/core/globals.h index f809c0af8..18492df95 100644 --- a/core/globals.h +++ b/core/globals.h @@ -188,7 +188,7 @@ typedef HANDLE file_t; # if defined(MACOS) || defined(ANDROID) typedef unsigned long ulong; # endif -# include "types_wrapper.h" /* for wait */ +# include "types_wrapper.h" /* for wait */ # define DIRSEP '/' # define ALT_DIRSEP DIRSEP #endif diff --git a/core/lib/globals_shared.h b/core/lib/globals_shared.h index 29e39a5dc..2ca25a0ce 100644 --- a/core/lib/globals_shared.h +++ b/core/lib/globals_shared.h @@ -963,9 +963,9 @@ typedef struct { uint flags : 2; int ignored2; /* siginfo_t.si_code: has meaning to kernel so we avoid using */ #else - uint version; /* version number for future proofing */ - uint nudge_action_mask; /* drawn from NUDGE_DEFS above */ - uint flags; /* flags drawn from above enum */ + uint version; /* version number for future proofing */ + uint nudge_action_mask; /* drawn from NUDGE_DEFS above */ + uint flags; /* flags drawn from above enum */ #endif client_id_t client_id; /* unique ID identifying client */ uint64 client_arg; /* argument for a client nudge */ diff --git a/ext/drsyms/drsyms_unix_frontend.c b/ext/drsyms/drsyms_unix_frontend.c index ac517abad..237b91dad 100644 --- a/ext/drsyms/drsyms_unix_frontend.c +++ b/ext/drsyms/drsyms_unix_frontend.c @@ -206,8 +206,8 @@ drsym_init(int shmid_in) */ } else { hashtable_init_ex(&modtable, MODTABLE_HASH_BITS, HASH_STRING, true /*strdup*/, - false /*!synch: using symbol_lock*/, - drsym_unix_unload, NULL, NULL); + false /*!synch: using symbol_lock*/, drsym_unix_unload, NULL, + NULL); } return DRSYM_SUCCESS; } From 36db80723d38bf795c1de278338efcc8ee1a251b Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 2 Jun 2026 01:59:30 +0000 Subject: [PATCH 018/156] Pull in definitions of `interrupt_vector_t` and `interrupt_handler_t` --- core/arch/arch_exports.h | 49 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/core/arch/arch_exports.h b/core/arch/arch_exports.h index 270942fcd..f2f46b251 100644 --- a/core/arch/arch_exports.h +++ b/core/arch/arch_exports.h @@ -1879,4 +1879,53 @@ typedef struct _rseq_entry_state_t { # define ARCH_SUPPORTS_HW_CACHE_CONSISTENCY #endif +#ifdef LINUX_KERNEL +typedef enum { + VECTOR_DIVIDE_ERROR = 0, + VECTOR_START = VECTOR_DIVIDE_ERROR, + VECTOR_EXCEPTION_START = VECTOR_DIVIDE_ERROR, + VECTOR_DEBUG = 1, + VECTOR_NMI = 2, + VECTOR_BREAKPOINT = 3, + VECTOR_OVERFLOW = 4, + VECTOR_BOUND_RANGE_EXCEEDED = 5, + VECTOR_INVALID_OPCODE = 6, + VECTOR_DEVICE_NOT_AVAILABLE = 7, + VECTOR_DOUBLE_FAULT = 8, + VECTOR_COPROCESSOR_SEGMENT_OVERRUN = 9, + VECTOR_INVALID_TSS = 10, + VECTOR_SEGMENT_NOT_PRESENT = 11, + VECTOR_STACK_FAULT = 12, + VECTOR_GENERAL_PROTECTION = 13, + VECTOR_PAGE_FAULT = 14, + /* no 15 */ + VECTOR_X87_FPU_FLOATING_POINT_ERROR = 16, + VECTOR_ALIGNMENT_CHECK = 17, + VECTOR_MACHINE_CHECK = 18, + VECTOR_SIMD_FLOATING_POINT = 19, + VECTOR_EXCEPTION_END = 20, + VECTOR_INTERRUPT_START = 20, + VECTOR_INTERRUPT_END = 256, + VECTOR_END = VECTOR_INTERRUPT_END +} interrupt_vector_t; + +# define MAGIC_FAKE_ERROR 0xfffffffffbadbeef + +/* The layout of the interrupt stack frame. The stack pointer will point to + * error_code. */ +typedef struct { + reg_t error_code; + byte *xip; + reg_t cs; + reg_t xflags; + reg_t xsp; + reg_t ss; +} interrupt_stack_frame_t; + +# define INTERRUPT_STACK_FRAME_ALIGNMENT 0x10 + +typedef void (*interrupt_handler_t)(interrupt_stack_frame_t *, dr_mcontext_t *, + interrupt_vector_t); +#endif /* LINUX_KERNEL */ + #endif /* _ARCH_EXPORTS_H_ */ From 9c375cdbbeb471239c118c1840641b6c1e063402 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 2 Jun 2026 02:03:39 +0000 Subject: [PATCH 019/156] Avoid __DATE__ and __TIME__ in kernel builds --- core/buildmark.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/buildmark.c b/core/buildmark.c index 270341557..6c1d58858 100644 --- a/core/buildmark.c +++ b/core/buildmark.c @@ -34,7 +34,10 @@ #include "globals.h" -#if defined(__DATE__) && defined(__TIME__) +/* Avoid __DATE__ and __TIME__ in kernel builds to avoid errors from + * -Werror=date-time and to support reproducible builds. + */ +#if defined(__DATE__) && defined(__TIME__) && !defined(LINUX_KERNEL) const char dynamorio_buildmark[] = __DATE__ " " __TIME__; #else const char dynamorio_buildmark[] = "unknown"; From d18f040e4c164d2a7d175b3bc9ec38d7cd6e67ea Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 2 Jun 2026 23:27:59 +0000 Subject: [PATCH 020/156] Exclude os_cxt from client_data_t in kernel builds --- core/globals.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/globals.h b/core/globals.h index 18492df95..e7b93a083 100644 --- a/core/globals.h +++ b/core/globals.h @@ -409,7 +409,9 @@ typedef struct _client_data_t { bool suspended; /* 2 other ways to point at a context for dr_{g,s}et_mcontext() */ priv_mcontext_t *cur_mc; +#ifndef LINUX_KERNEL os_cxt_ptr_t os_cxt; +#endif /* The error code of last failed API routine. Not updated on successful API calls * but only upon failures. From 3a31fcd91e6e8c1263329fa582850173df253d75 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 2 Jun 2026 23:29:39 +0000 Subject: [PATCH 021/156] Use wrapper for stdarg.h and stddef.h --- core/arch/arch.h | 10 +++++----- core/globals.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/arch/arch.h b/core/arch/arch.h index 4e170d97c..0561dde1d 100644 --- a/core/arch/arch.h +++ b/core/arch/arch.h @@ -44,11 +44,11 @@ #ifndef ARCH_H #define ARCH_H -#include /* for offsetof */ -#include "instr.h" /* for reg_id_t */ -#include "decode.h" /* for X64_CACHE_MODE_DC */ -#include "arch_exports.h" /* for FRAG_IS_32 and FRAG_IS_X86_TO_X64 */ -#include "../fragment.h" /* IS_IBL_TARGET */ +#include "stddef_wrapper.h" /* for offsetof */ +#include "instr.h" /* for reg_id_t */ +#include "decode.h" /* for X64_CACHE_MODE_DC */ +#include "arch_exports.h" /* for FRAG_IS_32 and FRAG_IS_X86_TO_X64 */ +#include "../fragment.h" /* IS_IBL_TARGET */ #include "ir_utils.h" #if defined(X86) && defined(X64) diff --git a/core/globals.h b/core/globals.h index e7b93a083..c0de2effa 100644 --- a/core/globals.h +++ b/core/globals.h @@ -1096,7 +1096,7 @@ enum { DUMP_XML = true, DUMP_NOT_XML = false }; /* io.c */ /* to avoid transparency problems we must have our own vnsprintf and sscanf */ -#include /* for va_list */ +#include "stdarg_wrapper.h" /* for va_list */ int d_r_snprintf(char *s, size_t max, const char *fmt, ...); int From e603f877016f5821bd877ec0bbe5454cedc00393 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 2 Jun 2026 23:40:02 +0000 Subject: [PATCH 022/156] Exclude dr_stat_syscall from kernel builds `stat64` is defined in `` which isn't available in kernel builds. Besides, this function is not needed by drk. --- core/drlibc/drlibc.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/drlibc/drlibc.h b/core/drlibc/drlibc.h index abd0f7d02..1f24d716e 100644 --- a/core/drlibc/drlibc.h +++ b/core/drlibc/drlibc.h @@ -149,8 +149,10 @@ find_script_interpreter(DR_PARAM_OUT script_interpreter_t *result, DR_PARAM_IN const char *fname, ssize_t (*reader)(const char *pathname, void *buf, size_t count)); +# ifndef LINUX_KERNEL ptr_int_t dr_stat_syscall(const char *fname, struct stat64 *st); +# endif #endif /* UNIX */ #if defined(WINDOWS) && !defined(X64) From 40600e4a36dfb5f175bbd96cecdc74d1ce13b29a Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 3 Jun 2026 00:08:09 +0000 Subject: [PATCH 023/156] Provide definition for wchar_t in kernel builds --- core/globals.h | 3 ++- core/stddef_wrapper.h | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/core/globals.h b/core/globals.h index c0de2effa..d6078ea77 100644 --- a/core/globals.h +++ b/core/globals.h @@ -188,7 +188,8 @@ typedef HANDLE file_t; # if defined(MACOS) || defined(ANDROID) typedef unsigned long ulong; # endif -# include "types_wrapper.h" /* for wait */ +# include "stddef_wrapper.h" /* for wchar_t */ +# include "types_wrapper.h" /* for wait */ # define DIRSEP '/' # define ALT_DIRSEP DIRSEP #endif diff --git a/core/stddef_wrapper.h b/core/stddef_wrapper.h index bbe953c6e..3114dee99 100644 --- a/core/stddef_wrapper.h +++ b/core/stddef_wrapper.h @@ -5,6 +5,10 @@ #ifdef LINUX_KERNEL # include +# ifndef _WCHAR_T_DEFINED +# define _WCHAR_T_DEFINED +typedef __WCHAR_TYPE__ wchar_t; +# endif #else # include #endif From 77fce8c6849f0570d46adf7eed1c0e82d99f507d Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 3 Jun 2026 00:59:36 +0000 Subject: [PATCH 024/156] Pull in changes from drk These changes handle that `getenv()` is not available in kernel env. --- core/config.c | 8 +++++++- core/dynamo.c | 12 +++++++----- core/utils.c | 28 ++++++++++++++++------------ 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/core/config.c b/core/config.c index 385435c72..5ac666367 100644 --- a/core/config.c +++ b/core/config.c @@ -45,6 +45,10 @@ # include "ntdll.h" # endif +# ifdef LINUX_KERNEL +# include "kernel_interface.h" +# endif + /* DYNAMORIO_VAR_CONFIGDIR is searched first, and then these: */ # ifdef UNIX # define GLOBAL_CONFIG_DIR "/etc/dynamorio" @@ -192,7 +196,9 @@ static config_vals_t *config_reread_vals; const char * my_getenv(IF_WINDOWS_ELSE_NP(const wchar_t *, const char *) var, char *buf, size_t bufsz) { -# ifdef UNIX +# ifdef LINUX_KERNEL + return kernel_getenv(var); +# elif defined(UNIX) return getenv(var); # else wchar_t wbuf[MAX_CONFIG_VALUE]; diff --git a/core/dynamo.c b/core/dynamo.c index 5e67f08a3..5036267bc 100644 --- a/core/dynamo.c +++ b/core/dynamo.c @@ -417,10 +417,11 @@ dynamorio_app_init_part_one_options(void) /* avoid time() for libc independence */ DODEBUG(starttime = query_time_seconds();); -#ifdef UNIX +#ifndef LINUX_KERNEL +# ifdef UNIX if (getenv(DYNAMORIO_VAR_EXECVE) != NULL) { post_execve = true; -# ifdef VMX86_SERVER +# ifdef VMX86_SERVER /* PR 458917: our gdt slot was not cleared on exec so we need to * clear it now to ensure we don't leak it and eventually run out of * slots. We could alternatively call os_tls_exit() prior to @@ -429,7 +430,7 @@ dynamorio_app_init_part_one_options(void) * TLS index we had. */ os_tls_pre_init(atoi(getenv(DYNAMORIO_VAR_EXECVE))); -# endif +# endif /* important to remove it, don't want to propagate to forked children, etc. */ /* i#909: unsetenv is unsafe as it messes up auxv access, so we disable */ disable_env(DYNAMORIO_VAR_EXECVE); @@ -437,6 +438,7 @@ dynamorio_app_init_part_one_options(void) ASSERT(getenv(DYNAMORIO_VAR_EXECVE) == NULL); } else post_execve = false; +# endif #endif /* default non-zero dynamo settings (options structure is @@ -789,7 +791,7 @@ dynamorio_app_init_part_two_finalize(void) return SUCCESS; } -#ifdef UNIX +#if defined(UNIX) && !defined(LINUX_KERNEL) void dynamorio_fork_init(dcontext_t *dcontext) { @@ -896,7 +898,7 @@ dynamorio_fork_init(dcontext_t *dcontext) instrument_fork_init(dcontext); } } -#endif /* UNIX */ +#endif /* UNIX && !LINUX_KERNEL */ /* To make DynamoRIO useful as a library for a standalone client * application (as opposed to a client library that works with diff --git a/core/utils.c b/core/utils.c index 370bbb06d..d75fc9e60 100644 --- a/core/utils.c +++ b/core/utils.c @@ -2665,14 +2665,17 @@ enable_new_log_dir() void create_log_dir(int dir_type) { -#ifdef UNIX +#ifdef LINUX_KERNEL + ASSERT_NOT_IMPLEMENTED(false); +#else +# ifdef UNIX char *pre_execve = getenv(DYNAMORIO_VAR_EXECVE_LOGDIR); DEBUG_DECLARE(bool sharing_logdir = false;) -#endif +# endif /* synchronize */ acquire_recursive_lock(&logdir_mutex); SELF_UNPROTECT_DATASEC(DATASEC_RARELY_PROT); -#ifdef UNIX +# ifdef UNIX if (dir_type == PROCESS_DIR && pre_execve != NULL) { /* if this app has a logdir option or config, that should trump sharing * the pre-execve logdir. a logdir env var should not. @@ -2692,7 +2695,7 @@ create_log_dir(int dir_type) /* check that it's gone: we've had problems with unsetenv */ ASSERT(getenv(DYNAMORIO_VAR_EXECVE_LOGDIR) == NULL); } -#endif +# endif /* used to be an else: leaving indentation though */ if (dir_type == BASE_DIR) { int retval; @@ -2715,21 +2718,21 @@ create_log_dir(int dir_type) basedir_initialized = true; /* skip creating dir basedir if is empty */ if (basedir[0] == '\0') { -#ifndef STATIC_LIBRARY +# ifndef STATIC_LIBRARY SYSLOG(SYSLOG_WARNING, WARNING_EMPTY_OR_NONEXISTENT_LOGDIR_KEY, 2, get_application_name(), get_application_pid()); -#endif +# endif } else { if (!os_create_dir(basedir, CREATE_DIR_ALLOW_EXISTING)) { /* try to create full path */ char swap; char *end = double_strchr(basedir, DIRSEP, ALT_DIRSEP); bool res; -#ifdef WINDOWS +# ifdef WINDOWS /* skip the drive */ if (end != NULL && end > basedir && *(end - 1) == ':') end = double_strchr(++end, DIRSEP, ALT_DIRSEP); -#endif +# endif while (end) { swap = *end; *end = '\0'; @@ -2771,7 +2774,7 @@ create_log_dir(int dir_type) SELF_PROTECT_DATASEC(DATASEC_RARELY_PROT); release_recursive_lock(&logdir_mutex); -#ifdef DEBUG +# ifdef DEBUG if (d_r_stats != NULL) { /* if null, we're trying to report an error (probably via a core dump), * so who cares if we lose logdir name */ @@ -2779,12 +2782,13 @@ create_log_dir(int dir_type) d_r_stats->logdir[sizeof(d_r_stats->logdir) - 1] = '\0'; /* if max no null */ } if (dir_type == PROCESS_DIR -# ifdef UNIX +# ifdef UNIX && !sharing_logdir -# endif +# endif ) SYSLOG_INTERNAL_INFO("log dir=%s", logdir); -#endif /* DEBUG */ +# endif /* DEBUG */ +#endif /* LINUX_KERNEL */ } /* Copies the name of the specified directory into buffer, returns true if From a031e5d72e8c92a1ad1aa64b857ebb070e0babc4 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 3 Jun 2026 01:01:47 +0000 Subject: [PATCH 025/156] Add explicit void to function prototypes --- core/annotations.h | 4 ++-- core/arch/arch.h | 10 +++++----- core/lib/dr_events.h | 4 ++-- core/lib/instrument.h | 2 +- core/module_shared.h | 2 +- core/synch.h | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/core/annotations.h b/core/annotations.h index e4e927eea..680306072 100644 --- a/core/annotations.h +++ b/core/annotations.h @@ -124,10 +124,10 @@ typedef struct _dr_annotation_handler_t { } dr_annotation_handler_t; void -annotation_init(); +annotation_init(void); void -annotation_exit(); +annotation_exit(void); static inline bool is_annotation_label(instr_t *instr) diff --git a/core/arch/arch.h b/core/arch/arch.h index 0561dde1d..53ebb756a 100644 --- a/core/arch/arch.h +++ b/core/arch/arch.h @@ -293,7 +293,7 @@ extern bool d_r_client_avx512_code_in_use; /* This routine determines whether zmm registers should be saved. */ static inline bool -d_r_is_avx512_code_in_use() +d_r_is_avx512_code_in_use(void) { return *d_r_avx512_code_in_use; } @@ -325,13 +325,13 @@ d_r_set_avx512_code_in_use(bool in_use, app_pc pc) } static inline bool -d_r_is_client_avx512_code_in_use() +d_r_is_client_avx512_code_in_use(void) { return d_r_client_avx512_code_in_use; } static inline void -d_r_set_client_avx512_code_in_use() +d_r_set_client_avx512_code_in_use(void) { SELF_UNPROTECT_DATASEC(DATASEC_RARELY_PROT); ATOMIC_1BYTE_WRITE(&d_r_client_avx512_code_in_use, (bool)true, false); @@ -648,7 +648,7 @@ mangle_insert_clone_code(dcontext_t *dcontext, instrlist_t *ilist, /* Returns the number of bytes the stack pointer has to be aligned to. */ static inline uint -get_ABI_stack_alignment() +get_ABI_stack_alignment(void) { return ABI_STACK_ALIGNMENT; } @@ -1094,7 +1094,7 @@ cache_pc trace_head_return_coarse_routine(IF_X86_64(gencode_mode_t mode)); /* shared clean call context switch */ bool -client_clean_call_is_thread_private(); +client_clean_call_is_thread_private(void); cache_pc get_clean_call_save(dcontext_t *dcontext _IF_X86_64(gencode_mode_t mode)); cache_pc diff --git a/core/lib/dr_events.h b/core/lib/dr_events.h index ea5ce1fac..e86007ede 100644 --- a/core/lib/dr_events.h +++ b/core/lib/dr_events.h @@ -1478,7 +1478,7 @@ DR_API * whenever virtual memory is tight and enables the client to help free space. */ void -dr_register_low_on_memory_event(void (*func)()); +dr_register_low_on_memory_event(void (*func)(void)); DR_API /** @@ -1487,7 +1487,7 @@ DR_API * (e.g., the function was not registered). */ bool -dr_unregister_low_on_memory_event(void (*func)()); +dr_unregister_low_on_memory_event(void (*func)(void)); DR_API /** diff --git a/core/lib/instrument.h b/core/lib/instrument.h index c5bd4989f..fe938823c 100644 --- a/core/lib/instrument.h +++ b/core/lib/instrument.h @@ -139,7 +139,7 @@ instrument_post_syscall(dcontext_t *dcontext, int sysnum); bool instrument_invoke_another_syscall(dcontext_t *dcontext); void -instrument_low_on_memory(); +instrument_low_on_memory(void); /* returns whether a client event was called which might have changed the context */ bool instrument_kernel_xfer(dcontext_t *dcontext, dr_kernel_xfer_type_t type, diff --git a/core/module_shared.h b/core/module_shared.h index 0ad2bf92d..1934d576b 100644 --- a/core/module_shared.h +++ b/core/module_shared.h @@ -565,7 +565,7 @@ os_loader_init_prologue(void); * will release privload_lock. */ void -os_loader_init_epilogue(); +os_loader_init_epilogue(void); void os_loader_exit(void); diff --git a/core/synch.h b/core/synch.h index 92e8e1817..9ca80cdb6 100644 --- a/core/synch.h +++ b/core/synch.h @@ -268,7 +268,7 @@ detach_on_permanent_stack(bool internal, bool do_cleanup, dr_stats_t *drstats); #ifdef LINUX void -detach_externally_on_new_stack(); +detach_externally_on_new_stack(void); #endif /*** exported for detach only ***/ From 145d5b1919946d11fabbf6963dd264b10ad44883 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 3 Jun 2026 01:32:17 +0000 Subject: [PATCH 026/156] Use relative path of stddef_wrapper.h in arch.h --- core/arch/arch.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/arch/arch.h b/core/arch/arch.h index 53ebb756a..f92aeb696 100644 --- a/core/arch/arch.h +++ b/core/arch/arch.h @@ -44,11 +44,11 @@ #ifndef ARCH_H #define ARCH_H -#include "stddef_wrapper.h" /* for offsetof */ -#include "instr.h" /* for reg_id_t */ -#include "decode.h" /* for X64_CACHE_MODE_DC */ -#include "arch_exports.h" /* for FRAG_IS_32 and FRAG_IS_X86_TO_X64 */ -#include "../fragment.h" /* IS_IBL_TARGET */ +#include "../stddef_wrapper.h" /* for offsetof */ +#include "instr.h" /* for reg_id_t */ +#include "decode.h" /* for X64_CACHE_MODE_DC */ +#include "arch_exports.h" /* for FRAG_IS_32 and FRAG_IS_X86_TO_X64 */ +#include "../fragment.h" /* IS_IBL_TARGET */ #include "ir_utils.h" #if defined(X86) && defined(X64) From e158c352620d02a6d05874cc2f8404c775a21e3c Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 3 Jun 2026 01:51:28 +0000 Subject: [PATCH 027/156] Use limits_wrapper.h in heap.c --- core/heap.c | 2 +- core/limits_wrapper.h | 40 ++++++++++++++++++++++------------------ 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/core/heap.c b/core/heap.c index 92c89629e..698c5883c 100644 --- a/core/heap.c +++ b/core/heap.c @@ -40,7 +40,7 @@ */ #include "globals.h" -#include +#include "limits_wrapper.h" #include "fragment.h" /* for struct sizes */ #include "link.h" /* for struct sizes */ diff --git a/core/limits_wrapper.h b/core/limits_wrapper.h index c61087e50..e32c3afef 100644 --- a/core/limits_wrapper.h +++ b/core/limits_wrapper.h @@ -1,31 +1,35 @@ -#ifndef __LIMITS_H_ -#define __LIMITS_H_ -/* Copied from /usr/include/limits.h */ -/* We don't have #include_next. - Define ANSI for standard 32-bit words. */ +#ifndef __LIMITS_WRAPPER_H_ +#define __LIMITS_WRAPPER_H_ -/* These assume 8-bit `char's, 16-bit `short int's, - and 32-bit `int's and `long int's. */ +#include "configure.h" -#include +#ifdef LINUX_KERNEL +/* The Linux kernel does not have a standard limits.h for basic C types, + * but it defines some integer limits in . We include that + * and manually define the standard C char/byte limits here. + */ +# include /* Number of bits in a `char'. */ -#define CHAR_BIT 8 +# define CHAR_BIT 8 /* Minimum and maximum values a `signed char' can hold. */ -#define SCHAR_MIN (-128) -#define SCHAR_MAX 127 +# define SCHAR_MIN (-128) +# define SCHAR_MAX 127 /* Maximum value an `unsigned char' can hold. (Minimum is 0.) */ -#define UCHAR_MAX 255 +# define UCHAR_MAX 255 /* Minimum and maximum values a `char' can hold. */ -#ifdef __CHAR_UNSIGNED__ -# define CHAR_MIN 0 -# define CHAR_MAX UCHAR_MAX +# ifdef __CHAR_UNSIGNED__ +# define CHAR_MIN 0 +# define CHAR_MAX UCHAR_MAX +# else +# define CHAR_MIN SCHAR_MIN +# define CHAR_MAX SCHAR_MAX +# endif #else -# define CHAR_MIN SCHAR_MIN -# define CHAR_MAX SCHAR_MAX +# include #endif -#endif +#endif /* __LIMITS_WRAPPER_H_ */ From 77624d093908bc0fcd8bb450060d2a50efe98b9e Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 3 Jun 2026 01:58:27 +0000 Subject: [PATCH 028/156] Use wrapper headers in fcache.c and fragment.c --- core/fcache.c | 4 ++-- core/fragment.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/fcache.c b/core/fcache.c index 945235452..27fbe750c 100644 --- a/core/fcache.c +++ b/core/fcache.c @@ -47,8 +47,8 @@ #ifdef HOT_PATCHING_INTERFACE # include "hotpatch.h" #endif -#include /* for offsetof */ -#include /* for UCHAR_MAX */ +#include "stddef_wrapper.h" /* for offsetof */ +#include "limits_wrapper.h" /* for UCHAR_MAX */ #include "perscache.h" #include "synch.h" #include "instrument.h" diff --git a/core/fragment.c b/core/fragment.c index a8b5680fb..c4459dbeb 100644 --- a/core/fragment.c +++ b/core/fragment.c @@ -46,8 +46,8 @@ #include "emit.h" #include "monitor.h" #include "instrument.h" -#include /* for offsetof */ -#include /* UINT_MAX */ +#include "stddef_wrapper.h" /* for offsetof */ +#include "limits_wrapper.h" /* UINT_MAX */ #include "perscache.h" #include "synch.h" #ifdef UNIX From d46c9f0e60dcb0878301c2228ec05003cea4e894 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 3 Jun 2026 13:52:24 -0700 Subject: [PATCH 029/156] Add explicit void to function definitions in C files Ensure function definitions in .c files are consistent with the prototypes already updated in the corresponding header files. --- core/annotations.c | 4 ++-- core/heap.c | 2 +- core/lib/instrument.c | 2 +- core/synch.c | 2 +- core/unix/os.c | 4 ++-- core/win32/ntdll.c | 2 +- core/win32/os.c | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/core/annotations.c b/core/annotations.c index 516355192..32608c199 100644 --- a/core/annotations.c +++ b/core/annotations.c @@ -258,7 +258,7 @@ free_annotation_handler(void *p); */ void -annotation_init() +annotation_init(void) { handlers = strhash_hash_create( GLOBAL_DCONTEXT, 8, 80, /* favor a small table */ @@ -302,7 +302,7 @@ annotation_init() } void -annotation_exit() +annotation_exit(void) { # if !(defined(WINDOWS) && defined(X64)) uint i; diff --git a/core/heap.c b/core/heap.c index 698c5883c..d7b90ce20 100644 --- a/core/heap.c +++ b/core/heap.c @@ -1552,7 +1552,7 @@ reached_beyond_vmm(which_vmm_t which) } void -vmm_heap_handle_pending_low_on_memory_event_trigger() +vmm_heap_handle_pending_low_on_memory_event_trigger(void) { bool trigger = false; diff --git a/core/lib/instrument.c b/core/lib/instrument.c index 1e220f75a..910f09493 100644 --- a/core/lib/instrument.c +++ b/core/lib/instrument.c @@ -1521,7 +1521,7 @@ instrument_fork_init(dcontext_t *dcontext) #endif void -instrument_low_on_memory() +instrument_low_on_memory(void) { call_all(low_on_memory_callbacks, int (*)()); } diff --git a/core/synch.c b/core/synch.c index c4d020dc7..fe423d45a 100644 --- a/core/synch.c +++ b/core/synch.c @@ -2329,7 +2329,7 @@ detach_on_permanent_stack(bool internal, bool do_cleanup, dr_stats_t *drstats) #ifdef LINUX void -detach_externally_on_new_stack() +detach_externally_on_new_stack(void) { dcontext_t *my_dcontext; priv_mcontext_t my_mcontext; diff --git a/core/unix/os.c b/core/unix/os.c index dcd1c39d8..b50b97226 100644 --- a/core/unix/os.c +++ b/core/unix/os.c @@ -1275,7 +1275,7 @@ set_app_args(DR_PARAM_IN int *app_argc_in, DR_PARAM_IN char **app_argv_in) /* Returns the number of application's command-line arguments. */ int -num_app_args() +num_app_args(void) { if (!DYNAMO_OPTION(early_inject)) { set_client_error_code(NULL, DR_ERROR_NOT_IMPLEMENTED); @@ -1442,7 +1442,7 @@ query_time_millis() /* microseconds since 1601 */ uint64 -query_time_micros() +query_time_micros(void) { struct timeval current_time; uint64 val = dynamorio_syscall(SYS_gettimeofday, 2, ¤t_time, NULL); diff --git a/core/win32/ntdll.c b/core/win32/ntdll.c index 906c5bfa3..b5822615d 100644 --- a/core/win32/ntdll.c +++ b/core/win32/ntdll.c @@ -3369,7 +3369,7 @@ query_time_100ns() } uint64 -query_time_micros() +query_time_micros(void) { LONGLONG time100ns = query_time_100ns(); return ((uint64)time100ns / TIMER_UNITS_PER_MICROSECOND); diff --git a/core/win32/os.c b/core/win32/os.c index fc95edb36..55f0028e4 100644 --- a/core/win32/os.c +++ b/core/win32/os.c @@ -3225,7 +3225,7 @@ is_phandle_me(HANDLE phandle) /* Returns the number of application's command-line arguments. */ int -num_app_args() +num_app_args(void) { /* XXX i#2662: Add support for Windows. */ ASSERT_NOT_IMPLEMENTED(false); From 5b072778866a2b0cd8dacae45d58a296fd69fe5b Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 3 Jun 2026 14:39:56 -0700 Subject: [PATCH 030/156] Do not define MAX/MIN in DR when building the kernel modules --- core/drk.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/drk.mk b/core/drk.mk index 7608dbc68..0143d2c45 100644 --- a/core/drk.mk +++ b/core/drk.mk @@ -10,7 +10,7 @@ API_INCLUDE_DIR ?= lib/include .PHONY: test DR_CORE_DIR := $(shell pwd) -DR_INCLUDE_FLAGS := -DDR_REG_ENUM_COMPATIBILITY -DLINUX_KERNEL -DDYNAMORIO_INTERNAL\ +DR_INCLUDE_FLAGS := -DDR_REG_ENUM_COMPATIBILITY -DLINUX_KERNEL -DDYNAMORIO_INTERNAL -DDR_DO_NOT_DEFINE_MAX_MIN\ -I$(DR_CORE_DIR)/../build\ -I$(DR_CORE_DIR)/$(API_INCLUDE_DIR)\ -I$(DR_CORE_DIR)\ From da9e3577b2b798125be75ef5f9f6f73b38657645 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 3 Jun 2026 14:41:04 -0700 Subject: [PATCH 031/156] Do not define printf and others in kernel builds --- core/globals.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/core/globals.h b/core/globals.h index d6078ea77..b88209b74 100644 --- a/core/globals.h +++ b/core/globals.h @@ -1199,13 +1199,15 @@ strtoul(const char *str, char **end, int base); #endif #if !defined(NOT_DYNAMORIO_CORE_PROPER) && !defined(NOT_DYNAMORIO_CORE) -# undef printf -# define printf printf_forbidden_function -# undef sprintf /* defined on macos */ -# define sprintf sprintf_forbidden_function -# define swprintf swprintf_forbidden_function -# undef vsprintf /* defined on macos */ -# define vsprintf vsprintf_forbidden_function +# ifndef LINUX_KERNEL +# undef printf +# define printf printf_forbidden_function +# undef sprintf /* defined on macos */ +# define sprintf sprintf_forbidden_function +# define swprintf swprintf_forbidden_function +# undef vsprintf /* defined on macos */ +# define vsprintf vsprintf_forbidden_function +# endif /* libc independence */ # define mprotect mprotect_forbidden_function From 8e394d2633794186cf84719647400e8fea4ef44f Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 3 Jun 2026 14:42:59 -0700 Subject: [PATCH 032/156] Do not include in kernel builds --- core/ir/instr_create_shared_api.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/core/ir/instr_create_shared_api.h b/core/ir/instr_create_shared_api.h index a6a236696..3e8db72f6 100644 --- a/core/ir/instr_create_shared_api.h +++ b/core/ir/instr_create_shared_api.h @@ -56,7 +56,18 @@ # include "dr_ir_instr.h" // IWYU pragma: export # include "dr_ir_utils.h" // IWYU pragma: export #endif -#include /* For SCHAR_MAX, SCHAR_MIN. */ + +#ifdef LINUX_KERNEL +# include +# ifndef SCHAR_MAX +# define SCHAR_MAX 127 +# endif +# ifndef SCHAR_MIN +# define SCHAR_MIN (-128) +# endif +#else +# include /* For SCHAR_MAX, SCHAR_MIN. */ +#endif /** * Set the translation field for an instruction. For example: From 32701fcca459789feec99ed1bdffdca9e56ac16a Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 3 Jun 2026 14:50:12 -0700 Subject: [PATCH 033/156] Fix windows CI Add explicit void to the C core/lib/instrument.c to match the header. --- core/lib/instrument.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/lib/instrument.c b/core/lib/instrument.c index 910f09493..66a71b8f1 100644 --- a/core/lib/instrument.c +++ b/core/lib/instrument.c @@ -1212,13 +1212,13 @@ dr_unregister_fork_init_event(void (*func)(void *drcontext)) #endif void -dr_register_low_on_memory_event(void (*func)()) +dr_register_low_on_memory_event(void (*func)(void)) { add_callback(&low_on_memory_callbacks, (void (*)(void))func, true); } bool -dr_unregister_low_on_memory_event(void (*func)()) +dr_unregister_low_on_memory_event(void (*func)(void)) { return remove_callback(&low_on_memory_callbacks, (void (*)(void))func, true); } From 77bd29699c8a7f2ccb25dda23e7e19f1cfc4e821 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 3 Jun 2026 15:38:21 -0700 Subject: [PATCH 034/156] Fix windows CI --- ext/drmgr/drmgr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/drmgr/drmgr.c b/ext/drmgr/drmgr.c index 58b98bd3f..0a0a68316 100644 --- a/ext/drmgr/drmgr.c +++ b/ext/drmgr/drmgr.c @@ -459,7 +459,7 @@ static void drmgr_modunload_event(void *drcontext, const module_data_t *info); static void -drmgr_low_on_memory_event(); +drmgr_low_on_memory_event(void); static void drmgr_kernel_xfer_event(void *drcontext, const dr_kernel_xfer_info_t *info); @@ -3500,7 +3500,7 @@ drmgr_unregister_low_on_memory_event_user_data(void (*func)(void *user_data)) } static void -drmgr_low_on_memory_event() +drmgr_low_on_memory_event(void) { void *drcontext = dr_get_current_drcontext(); generic_event_entry_t local[EVENTS_STACK_SZ]; From eaf840e22212336d5d298bc87b985dd46e7e58f4 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 3 Jun 2026 15:47:26 -0700 Subject: [PATCH 035/156] Fix windows CI --- suite/tests/client-interface/events.dll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/suite/tests/client-interface/events.dll.c b/suite/tests/client-interface/events.dll.c index c06a9a270..5bbcd2214 100644 --- a/suite/tests/client-interface/events.dll.c +++ b/suite/tests/client-interface/events.dll.c @@ -169,7 +169,7 @@ check_result(void) } static void -low_on_memory_event() +low_on_memory_event(void) { /* Do nothing. Testing only register and unregister functions. */ } From c42a1d1541431ee185a2cae28657853985f01766 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 3 Jun 2026 15:54:58 -0700 Subject: [PATCH 036/156] Add explicit void to function prototypes --- core/jit_opt.c | 4 ++-- core/jit_opt.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/jit_opt.c b/core/jit_opt.c index 94abda28b..c1c9b6664 100644 --- a/core/jit_opt.c +++ b/core/jit_opt.c @@ -547,7 +547,7 @@ fragment_tree_clear(fragment_tree_t *tree) static fragment_tree_t *fragment_tree; void -jitopt_init() +jitopt_init(void) { if (DYNAMO_OPTION(opt_jit)) { fragment_tree = fragment_tree_create(); @@ -564,7 +564,7 @@ jitopt_init() } void -jitopt_exit() +jitopt_exit(void) { if (DYNAMO_OPTION(opt_jit)) fragment_tree_destroy(fragment_tree); diff --git a/core/jit_opt.h b/core/jit_opt.h index 961fc8b05..7402e73a0 100644 --- a/core/jit_opt.h +++ b/core/jit_opt.h @@ -2,10 +2,10 @@ #define _JIT_OPT_H_ void -jitopt_init(); +jitopt_init(void); void -jitopt_exit(); +jitopt_exit(void); /* Account for a DGC basic block having the specified span in app space. */ void From 301bc87d2a51e17ab7ff00ae7b22b7184a992208 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 3 Jun 2026 15:55:27 -0700 Subject: [PATCH 037/156] Do not include for kernel builds --- core/ir/x86/instr_create_api.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/ir/x86/instr_create_api.h b/core/ir/x86/instr_create_api.h index 1d4d29391..ed7fdd8d0 100644 --- a/core/ir/x86/instr_create_api.h +++ b/core/ir/x86/instr_create_api.h @@ -50,7 +50,9 @@ * the instr_shrink_to_16_bits() routine. */ -#include /* for floating-point math constants */ +#ifndef LINUX_KERNEL +# include /* for floating-point math constants */ +#endif /* instruction modification convenience routines */ /** From 45b5d42cf42458696533e9709783eb85c4fd298e Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Thu, 4 Jun 2026 23:09:17 +0000 Subject: [PATCH 038/156] Change NOINLINE definition to using the double-underscore variant --- core/lib/globals_api.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/lib/globals_api.h b/core/lib/globals_api.h index 13bd2d6de..779117230 100644 --- a/core/lib/globals_api.h +++ b/core/lib/globals_api.h @@ -173,7 +173,7 @@ typedef char bool; # define ALIGN_VAR(x) __attribute__((aligned(x))) # define INLINE_FORCED inline # define WEAK __attribute__((weak)) -# define NOINLINE __attribute__((noinline)) +# define NOINLINE __attribute__((__noinline__)) #endif /* We want a consistent size so we stay away from MAX_PATH. From 16a355b8114de80fa20392a06c616645488db1ad Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Thu, 4 Jun 2026 23:21:39 +0000 Subject: [PATCH 039/156] Exclude instrument_kernel_xfer from kernel builds --- core/lib/instrument.c | 10 ++++++++++ core/lib/instrument.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/core/lib/instrument.c b/core/lib/instrument.c index 66a71b8f1..3d1993747 100644 --- a/core/lib/instrument.c +++ b/core/lib/instrument.c @@ -252,9 +252,11 @@ static callback_list_t pre_syscall_callbacks = { static callback_list_t post_syscall_callbacks = { 0, }; +#ifndef LINUX_KERNEL static callback_list_t kernel_xfer_callbacks = { 0, }; +#endif #ifdef WINDOWS static callback_list_t exception_callbacks = { 0, @@ -873,7 +875,9 @@ free_all_callback_lists() free_callback_list(&filter_syscall_callbacks); free_callback_list(&pre_syscall_callbacks); free_callback_list(&post_syscall_callbacks); +#ifndef LINUX_KERNEL free_callback_list(&kernel_xfer_callbacks); +#endif #ifdef WINDOWS free_callback_list(&exception_callbacks); #else @@ -1314,6 +1318,7 @@ dr_unregister_post_syscall_event(void (*func)(void *drcontext, int sysnum)) return remove_callback(&post_syscall_callbacks, (void (*)(void))func, true); } +#ifndef LINUX_KERNEL void dr_register_kernel_xfer_event(void (*func)(void *drcontext, const dr_kernel_xfer_info_t *info)) @@ -1327,6 +1332,7 @@ dr_unregister_kernel_xfer_event(void (*func)(void *drcontext, { return remove_callback(&kernel_xfer_callbacks, (void (*)(void))func, true); } +#endif #ifdef PROGRAM_SHEPHERDING void @@ -2131,6 +2137,7 @@ instrument_invoke_another_syscall(dcontext_t *dcontext) return dcontext->client_data->invoke_another_syscall; } +#ifndef LINUX_KERNEL bool instrument_kernel_xfer(dcontext_t *dcontext, dr_kernel_xfer_type_t type, os_cxt_ptr_t source_os_cxt, dr_mcontext_t *source_dmc, @@ -2172,6 +2179,7 @@ instrument_kernel_xfer(dcontext_t *dcontext, dr_kernel_xfer_type_t type, dcontext->client_data->cur_mc = NULL; return true; } +#endif #ifdef WINDOWS /* Notify user of exceptions. Note: not called for RaiseException */ @@ -6866,6 +6874,7 @@ dr_redirect_execution(dr_mcontext_t *mcontext) dcontext->next_tag = canonicalize_pc_target(dcontext, mcontext->pc); dcontext->whereami = DR_WHERE_FCACHE; set_last_exit(dcontext, (linkstub_t *)get_client_linkstub()); +#ifndef LINUX_KERNEL if (kernel_xfer_callbacks.num > 0) { /* This can only be called from a clean call or an exception event. * For both of those we can get the current mcontext via dr_get_mcontext() @@ -6880,6 +6889,7 @@ dr_redirect_execution(dr_mcontext_t *mcontext) dr_mcontext_as_priv_mcontext(mcontext), 0)) dcontext->next_tag = canonicalize_pc_target(dcontext, mcontext->pc); } +#endif transfer_to_dispatch(dcontext, dr_mcontext_as_priv_mcontext(mcontext), true /*full_DR_state*/); /* on success we won't get here */ diff --git a/core/lib/instrument.h b/core/lib/instrument.h index fe938823c..0ff396a94 100644 --- a/core/lib/instrument.h +++ b/core/lib/instrument.h @@ -140,6 +140,7 @@ bool instrument_invoke_another_syscall(dcontext_t *dcontext); void instrument_low_on_memory(void); +#ifndef LINUX_KERNEL /* returns whether a client event was called which might have changed the context */ bool instrument_kernel_xfer(dcontext_t *dcontext, dr_kernel_xfer_type_t type, @@ -148,6 +149,7 @@ instrument_kernel_xfer(dcontext_t *dcontext, dr_kernel_xfer_type_t type, priv_mcontext_t *source_mc, app_pc target_pc, reg_t target_xsp, /* only one of these 2 should be non-NULL */ os_cxt_ptr_t target_os_cxt, priv_mcontext_t *target_mc, int sig); +#endif void instrument_nudge(dcontext_t *dcontext, client_id_t id, uint64 arg); From 2998cefe97bc5ebd3ac05c8462dd6835c5d67e4d Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Thu, 4 Jun 2026 23:22:10 +0000 Subject: [PATCH 040/156] Use limits_wrapper.h instead of limits.h --- core/hotpatch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/hotpatch.c b/core/hotpatch.c index 8de404513..bf9565374 100644 --- a/core/hotpatch.c +++ b/core/hotpatch.c @@ -52,7 +52,7 @@ #ifndef WINDOWS #endif -#include /* for ULLONG_MAX */ +#include "limits_wrapper.h" /* for ULLONG_MAX */ #include "fcache.h" /* for fcache_reset_all_caches_proactively */ #ifdef GBOP From 706585ae4b380bd00d61e2cd48a6843fd35d8c99 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Thu, 4 Jun 2026 23:22:40 +0000 Subject: [PATCH 041/156] Add explicit void to function prototypes --- core/heap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/heap.c b/core/heap.c index d7b90ce20..123459c34 100644 --- a/core/heap.c +++ b/core/heap.c @@ -350,7 +350,7 @@ release_landing_pad_mem(void); * DR areas lock first, to retry */ static bool -safe_to_allocate_or_free_heap_units() +safe_to_allocate_or_free_heap_units(void) { return ((!self_owns_recursive_lock(&global_alloc_lock) && !self_owns_recursive_lock(&heap_unit_lock)) || @@ -1569,7 +1569,7 @@ vmm_heap_handle_pending_low_on_memory_event_trigger(void) } static void -schedule_low_on_memory_event_trigger() +schedule_low_on_memory_event_trigger(void) { bool value = true; ATOMIC_1BYTE_WRITE(&low_on_memory_pending, value, false); @@ -2460,7 +2460,7 @@ d_r_heap_exit() } void -heap_post_exit() +heap_post_exit(void) { heap_exiting = false; } @@ -2471,7 +2471,7 @@ heap_post_exit() * need a test for hitting 2GB (or 3GB!) user mode limit. */ static void -heap_low_on_memory() +heap_low_on_memory(void) { /* free some memory! */ heap_unit_t *u, *next_u; From 675df412a8d4042476813835d5e85c0916ce2be0 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Thu, 4 Jun 2026 23:50:45 +0000 Subject: [PATCH 042/156] Exclude rseq function calls in fragment.c from kernel builds --- core/fragment.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/fragment.c b/core/fragment.c index c4459dbeb..aaa68285e 100644 --- a/core/fragment.c +++ b/core/fragment.c @@ -3036,7 +3036,7 @@ fragment_delete(dcontext_t *dcontext, fragment_t *f, uint actions) release_recursive_lock(&change_linking_lock); } -#ifdef LINUX +#if defined(LINUX) && !defined(LINUX_KERNEL) if (TEST(FRAG_HAS_RSEQ_ENDPOINT, f->flags)) rseq_remove_fragment(dcontext, f); #endif @@ -5430,7 +5430,7 @@ check_flush_queue(dcontext_t *dcontext, fragment_t *was_I_flushed) ATOMIC_4BYTE_ALIGNED_READ(&flushtime_global, &local_flushtime_global); if (DYNAMO_OPTION(shared_deletion) && pt->flushtime_last_update < local_flushtime_global) { -#ifdef LINUX +#if defined(LINUX) && !defined(LINUX_KERNEL) rseq_shared_fragment_flushtime_update(dcontext); #endif /* dec ref count on any pending shared areas */ From a1e8198b0c88424df6ade703309f15e3e34b9aa3 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Fri, 5 Jun 2026 00:08:35 +0000 Subject: [PATCH 043/156] Skip os_page_size_init in drk --- core/dynamo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/dynamo.c b/core/dynamo.c index 5036267bc..092b1cecf 100644 --- a/core/dynamo.c +++ b/core/dynamo.c @@ -407,7 +407,7 @@ dynamorio_app_init_part_one_options(void) } } else /* we do enter if nullcalls is on */ { -#ifdef UNIX +#if defined(UNIX) && !defined(LINUX_KERNEL) os_page_size_init((const char **)our_environ, is_our_environ_followed_by_auxv()); #endif #ifdef WINDOWS @@ -922,7 +922,7 @@ standalone_init(void) /* avoid issues w/ GLOBAL_DCONTEXT instead of thread dcontext */ dynamo_options.deadlock_avoidance = false; #endif -#ifdef UNIX +#if defined(UNIX) && !defined(LINUX_KERNEL) os_page_size_init((const char **)our_environ, is_our_environ_followed_by_auxv()); #endif #ifdef WINDOWS From 1dc69d14e5868d9ad7a24ba617956e7a6e102cba Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Fri, 5 Jun 2026 00:51:09 +0000 Subject: [PATCH 044/156] Fix format mismatch --- core/fcache.c | 2 +- core/heap.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/fcache.c b/core/fcache.c index 27fbe750c..bab58b6d5 100644 --- a/core/fcache.c +++ b/core/fcache.c @@ -4229,7 +4229,7 @@ fcache_reset_all_caches_proactively(uint target) LOG(GLOBAL, LOG_CACHE, 2, "fcache_reset_all_caches_proactively: walking the threads\n"); char buf[16]; - snprintf(buf, BUFFER_SIZE_ELEMENTS(buf), "%d", + snprintf(buf, BUFFER_SIZE_ELEMENTS(buf), SSZFMT, GLOBAL_STAT(num_bbs) + GLOBAL_STAT(num_traces)); NULL_TERMINATE_BUFFER(buf); SYSLOG(SYSLOG_INFORMATION, INFO_RESET_IN_PROGRESS, 3, buf, get_application_name(), diff --git a/core/heap.c b/core/heap.c index 123459c34..829ec1893 100644 --- a/core/heap.c +++ b/core/heap.c @@ -2565,7 +2565,7 @@ report_low_on_memory(which_vmm_t which, oom_source_t source, { if (TESTANY(DYNAMO_OPTION(silent_oom_mask), source) || silent_oom_for_process(source)) { - SYSLOG_INTERNAL_WARNING("Mostly silent OOM: %s " PFX ".\n", + SYSLOG_INTERNAL_WARNING("Mostly silent OOM: %s 0x%x.\n", get_oom_source_name(source), os_error_code); /* still produce an ldmp for internal use */ if (TEST(DUMPCORE_OUT_OF_MEM_SILENT, DYNAMO_OPTION(dumpcore_mask))) @@ -2573,10 +2573,10 @@ report_low_on_memory(which_vmm_t which, oom_source_t source, } else { const char *oom_source_code = get_oom_source_name(source); char type_hex[19]; - snprintf(type_hex, BUFFER_SIZE_ELEMENTS(type_hex), PFX, which); + snprintf(type_hex, BUFFER_SIZE_ELEMENTS(type_hex), "0x%x", which); NULL_TERMINATE_BUFFER(type_hex); char status_hex[19]; - snprintf(status_hex, BUFFER_SIZE_ELEMENTS(status_hex), PFX, os_error_code); + snprintf(status_hex, BUFFER_SIZE_ELEMENTS(status_hex), "0x%x", os_error_code); NULL_TERMINATE_BUFFER(status_hex); /* SYSLOG first */ SYSLOG(SYSLOG_CRITICAL, OUT_OF_MEMORY, 4, get_application_name(), From 4a6c23e351c26a3db8988c9a138e10afb0a1884a Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Fri, 5 Jun 2026 01:30:42 +0000 Subject: [PATCH 045/156] Change NOINLINE definition to using the double-underscore variant --- suite/tests/client-interface/drcallstack-test.c | 2 +- suite/tests/tools.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/suite/tests/client-interface/drcallstack-test.c b/suite/tests/client-interface/drcallstack-test.c index 13b54d8fe..328458b0b 100644 --- a/suite/tests/client-interface/drcallstack-test.c +++ b/suite/tests/client-interface/drcallstack-test.c @@ -33,7 +33,7 @@ #include "tools.h" #ifdef LINUX -# define NOINLINE __attribute__((noinline)) +# define NOINLINE __attribute__((__noinline__)) #else # error NYI #endif diff --git a/suite/tests/tools.h b/suite/tests/tools.h index 5526a5a92..edc7cc573 100644 --- a/suite/tests/tools.h +++ b/suite/tests/tools.h @@ -291,7 +291,7 @@ page_size(void) #else /* UNIX */ # define EXPORT __attribute__((visibility("default"))) # define IMPORT extern -# define NOINLINE __attribute__((noinline)) +# define NOINLINE __attribute__((__noinline__)) #endif /* convenience macros for secure string buffer operations */ From fdf658f6cf9e58d9b199478f330a7b72763f4213 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Fri, 5 Jun 2026 02:12:34 +0000 Subject: [PATCH 046/156] Exclude rseq function call in dispatch.c from kernel builds --- core/dispatch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/dispatch.c b/core/dispatch.c index 9c32a5eca..19c250298 100644 --- a/core/dispatch.c +++ b/core/dispatch.c @@ -992,7 +992,7 @@ dispatch_enter_dynamorio(dcontext_t *dcontext) ASSERT_NOT_REACHED(); } else if (dcontext->upcontext.upcontext.exit_reason == EXIT_REASON_RSEQ_ABORT) { -#ifdef LINUX +#if defined(LINUX) && !defined(LINUX_KERNEL) rseq_process_native_abort(dcontext); #else ASSERT_NOT_REACHED(); From 356f5febba1379d2d1f5ca974fc72c5c83bdd8ef Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Fri, 5 Jun 2026 05:08:59 +0000 Subject: [PATCH 047/156] Exclude dead code in dispatch.c for kernel builds --- core/dispatch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/dispatch.c b/core/dispatch.c index 19c250298..b89ff467a 100644 --- a/core/dispatch.c +++ b/core/dispatch.c @@ -135,7 +135,7 @@ d_r_dispatch(dcontext_t *dcontext) fragment_t coarse_f; #ifdef HAVE_TLS -# if defined(UNIX) && defined(X86) +# if defined(UNIX) && defined(X86) && !defined(LINUX_KERNEL) /* i#2089: the parent of a new thread has TLS in an unstable state * and needs to restore it prior to invoking get_thread_private_dcontext(). */ From e496141c9114a57d01395d14dc6aef422652c660 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Fri, 5 Jun 2026 05:17:57 +0000 Subject: [PATCH 048/156] Exclude dead code in dispatch.c from kernel builds --- core/dispatch.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/dispatch.c b/core/dispatch.c index b89ff467a..383507167 100644 --- a/core/dispatch.c +++ b/core/dispatch.c @@ -502,7 +502,7 @@ dispatch_enter_fcache(dcontext_t *dcontext, fragment_t *targetf) PC_AS_JMP_TGT(FRAG_ISA_MODE(targetf->flags), FCACHE_ENTRY_PC(targetf)) #endif ); -#ifdef UNIX +#if defined(UNIX) && !defined(LINUX_KERNEL) if (dcontext->signals_pending > 0) { /* i#2019: the fcache_enter generated code starts with a check for pending * signals, allowing the signal handling code to simply queue signals that @@ -1225,7 +1225,7 @@ dispatch_exit_fcache(dcontext_t *dcontext) } #endif -#ifdef UNIX +#if defined(UNIX) && !defined(LINUX_KERNEL) if (dcontext->signals_pending != 0) { /* XXX: We can overflow the app stack if we stack up too many signals * by interrupting prev handlers -- exacerbated by RAC lack of @@ -2134,7 +2134,7 @@ handle_system_call(dcontext_t *dcontext) break; #endif } while (repeat); -#ifdef UNIX +#if defined(UNIX) && !defined(LINUX_KERNEL) if (dcontext->signals_pending != 0) { /* i#2019: see comments in dispatch_enter_fcache() */ KSTOP(syscall_fcache); From 3a40641d9d1924c3fe1aeb16075a09dbd5a7c47a Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Fri, 5 Jun 2026 23:53:34 -0400 Subject: [PATCH 049/156] Exclude os_handle_mov_seg from kernel builds --- core/dispatch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/dispatch.c b/core/dispatch.c index 383507167..31c27f566 100644 --- a/core/dispatch.c +++ b/core/dispatch.c @@ -470,7 +470,7 @@ dispatch_enter_fcache(dcontext_t *dcontext, fragment_t *targetf) check_filter("linux.thread;linux.clone", get_short_name(get_application_name()))); #endif -#if defined(UNIX) && !defined(DGC_DIAGNOSTICS) && defined(X86) +#if defined(UNIX) && !defined(DGC_DIAGNOSTICS) && defined(X86) && !defined(LINUX_KERNEL) /* i#107: handle segment register usage conflicts between app and dr: * if the target fragment has an instr that updates the segment selector, * update the corresponding information maintained by DR. From 21791b9ef9af9da4dd24dcd12cce2c34ee310477 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Sat, 6 Jun 2026 00:13:22 -0400 Subject: [PATCH 050/156] Port changes from drk branch --- core/dispatch.c | 5 +++++ core/link.c | 26 ++++++++++++++++++++++++++ core/link.h | 12 ++++++++++++ 3 files changed, 43 insertions(+) diff --git a/core/dispatch.c b/core/dispatch.c index 31c27f566..df9f97d14 100644 --- a/core/dispatch.c +++ b/core/dispatch.c @@ -820,6 +820,10 @@ dispatch_enter_dynamorio(dcontext_t *dcontext) */ if (wherewasi == DR_WHERE_APP) { /* first entrance */ +#ifdef LINUX_KERNEL + ASSERT(dcontext->last_exit == get_starting_linkstub() || + IS_KERNEL_ENTRY_LINKSTUB(dcontext->last_exit)); +#else if (dcontext->last_exit == get_syscall_linkstub()) { /* i#813: the app hit our post-sysenter hook while native. * XXX: should we try to process ni syscalls here? But we're only @@ -837,6 +841,7 @@ dispatch_enter_dynamorio(dcontext_t *dcontext) /* new thread */ IF_WINDOWS_ELSE_0(dcontext->last_exit == get_asynch_linkstub())); } +#endif } else { /* MUST be set, if only to a fake linkstub_t */ ASSERT(dcontext->last_exit != NULL); diff --git a/core/link.c b/core/link.c index 8371ece84..6111a2083 100644 --- a/core/link.c +++ b/core/link.c @@ -187,6 +187,12 @@ static const linkstub_t linkstub_shared_syscall_bb = { static const linkstub_t linkstub_shared_syscall_unlinked = { LINK_FAKE, 0 }; #endif +#ifdef LINUX_KERNEL +static const linkstub_t linkstub_syscall_entry = { LINK_FAKE, 0 }; +static const linkstub_t linkstub_kernel_interrupt_entry = { LINK_FAKE, 0 }; +static const linkstub_t linkstub_user_interrupt_entry = { LINK_FAKE, 0 }; +#endif + /* A unique fragment_t for use when the details don't matter */ static const fragment_t coarse_fragment = { NULL, @@ -777,6 +783,26 @@ get_shared_syscalls_bb_linkstub() } #endif /* WINDOWS */ +#ifdef LINUX_KERNEL +const linkstub_t * +get_syscall_entry_linkstub() +{ + return &linkstub_syscall_entry; +} + +const linkstub_t * +get_user_interrupt_entry_linkstub() +{ + return &linkstub_user_interrupt_entry; +} + +const linkstub_t * +get_kernel_interrupt_entry_linkstub() +{ + return &linkstub_kernel_interrupt_entry; +} +#endif + #ifdef HOT_PATCHING_INTERFACE const linkstub_t * get_hot_patch_linkstub() diff --git a/core/link.h b/core/link.h index a359c668c..5cd374765 100644 --- a/core/link.h +++ b/core/link.h @@ -546,6 +546,18 @@ get_shared_syscalls_bb_linkstub(void); # define IS_SHARED_SYSCALLS_TRACE_LINKSTUB(l) false #endif +#ifdef LINUX_KERNEL +const linkstub_t * +get_syscall_entry_linkstub(void); +const linkstub_t * +get_user_interrupt_entry_linkstub(void); +const linkstub_t * +get_kernel_interrupt_entry_linkstub(void); +# define IS_KERNEL_ENTRY_LINKSTUB(l) \ + ((l) == get_syscall_entry_linkstub() || \ + (l) == get_user_interrupt_entry_linkstub()) +#endif + bool should_separate_stub(dcontext_t *dcontext, app_pc target, uint fragment_flags); int From 4063184d868c3dd67ee2d0be47e49d72b52e26bb Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Sun, 7 Jun 2026 00:07:18 -0400 Subject: [PATCH 051/156] Exclude dead code from kernel builds --- core/dispatch.c | 66 ++++++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/core/dispatch.c b/core/dispatch.c index df9f97d14..8026814ff 100644 --- a/core/dispatch.c +++ b/core/dispatch.c @@ -918,6 +918,7 @@ dispatch_enter_dynamorio(dcontext_t *dcontext) } #endif +#ifndef LINUX_KERNEL /* A non-ignorable syscall or cb return ending a bb must be acted on * We do it here to avoid becoming couldbelinking twice. * @@ -936,6 +937,7 @@ dispatch_enter_dynamorio(dcontext_t *dcontext) */ } } +#endif #ifdef WINDOWS else if (TEST(LINK_CALLBACK_RETURN, dcontext->last_exit->flags)) { handle_callback_return(dcontext); @@ -1798,7 +1800,7 @@ dispatch_exit_fcache_stats(dcontext_t *dcontext) * SYSTEM CALLS */ -#ifdef UNIX +#if defined(UNIX) && !defined(LINUX_KERNEL) static void adjust_syscall_continuation(dcontext_t *dcontext) { @@ -1858,6 +1860,7 @@ adjust_syscall_continuation(dcontext_t *dcontext) } #endif +#ifndef LINUX_KERNEL /* used to execute a system call instruction in the code cache * dcontext->next_tag is store elsewhere and restored after the system call * for resumption of execution post-syscall @@ -1872,23 +1875,23 @@ handle_system_call(dcontext_t *dcontext) int sysnum = os_normalized_sysnum((int)MCXT_SYSNUM_REG(mc), NULL, dcontext); app_pc saved_next_tag = dcontext->next_tag; bool repeat = false; -#ifdef WINDOWS +# ifdef WINDOWS /* make sure to ask about syscall before pre_syscall, which will swap new mc in! */ bool use_prev_dcontext = is_cb_return_syscall(dcontext); -#elif defined(X86) +# elif defined(X86) if (TEST(LINK_NI_SYSCALL_INT, dcontext->last_exit->flags)) { LOG(THREAD, LOG_SYSCALLS, 2, "Using do_int_syscall\n"); do_syscall = (app_pc)get_do_int_syscall_entry(dcontext); /* last_exit will be for the syscall so set a flag (could alternatively * set up a separate exit stub but this is simpler) */ dcontext->sys_was_int = true; -# ifdef VMX86_SERVER +# ifdef VMX86_SERVER if (is_vmkuw_sysnum(mc->xax)) { /* Even w/ syscall # shift int80 => ENOSYS */ do_syscall = get_do_vmkuw_syscall_entry(dcontext); LOG(THREAD, LOG_SYSCALLS, 2, "Using do_vmkuw_syscall\n"); } -# endif +# endif } else if (TEST(LINK_SPECIAL_EXIT, dcontext->last_exit->flags)) { if (dcontext->upcontext.upcontext.exit_reason == EXIT_REASON_NI_SYSCALL_INT_0x81) do_syscall = (app_pc)get_do_int81_syscall_entry(dcontext); @@ -1902,7 +1905,7 @@ handle_system_call(dcontext_t *dcontext) dcontext->sys_was_int = false; IF_NOT_X64(IF_VMX86(ASSERT(!is_vmkuw_sysnum(mc->xax)))); } -#endif +# endif /* We invoke here rather than inside pre_syscall() primarily so we can * set use_prev_dcontext(), but also b/c the windows and linux uses @@ -1925,10 +1928,10 @@ handle_system_call(dcontext_t *dcontext) LOG(THREAD, LOG_SYSCALLS, 2, "skipping syscall %d on client request\n", MCXT_SYSNUM_REG(mc)); } -#ifdef WINDOWS +# ifdef WINDOWS /* re-set in case client changed the number */ use_prev_dcontext = is_cb_return_syscall(dcontext); -#endif +# endif /* some syscalls require modifying local memory * XXX: move this unprot down to those syscalls to avoid unprot-prot-unprot-prot @@ -1941,10 +1944,10 @@ handle_system_call(dcontext_t *dcontext) LOG(THREAD, LOG_SYSCALLS, 2, "Entry into do_syscall to execute a non-ignorable system call\n"); -#ifdef SIDELINE +# ifdef SIDELINE /* clear cur-trace field so we don't think cur trace is still running */ sideline_trace = NULL; -#endif +# endif /* our flushing design assumes our syscall handlers are nolinking, * to avoid multiple-flusher deadlocks @@ -1962,14 +1965,14 @@ handle_system_call(dcontext_t *dcontext) */ dcontext->asynch_target = get_fcache_target(dcontext); -#ifdef WINDOWS +# ifdef WINDOWS if (get_syscall_method() == SYSCALL_METHOD_SYSENTER) { /* kernel sends control directly to 0x7ffe0304 so we need * to mangle the return address */ /* Ref case 5461 - edx will become top of stack post-syscall */ ASSERT(get_mcontext(dcontext)->xsp == get_mcontext(dcontext)->xdx); -# ifdef HOT_PATCHING_INTERFACE +# ifdef HOT_PATCHING_INTERFACE /* For hotp_only, vsyscall_syscall_end_pc can be NULL as dr will never * interp a system call. Also, for hotp_only, control can came here * from native only to do a syscall that was hooked. @@ -1977,9 +1980,9 @@ handle_system_call(dcontext_t *dcontext) ASSERT(!DYNAMO_OPTION(hotp_only) || (DYNAMO_OPTION(hotp_only) && dcontext->next_tag == BACK_TO_NATIVE_AFTER_SYSCALL)); -# else +# else ASSERT(vsyscall_syscall_end_pc != NULL || get_os_version() >= WINDOWS_VERSION_8); -# endif +# endif /* NOTE - the stack mangling must match that of intercept_nt_continue() * and shared_syscall as not all routines looking at the stack * differentiate. */ @@ -1987,10 +1990,10 @@ handle_system_call(dcontext_t *dcontext) /* win8 x86 syscalls have inlined sysenter routines */ (get_os_version() >= WINDOWS_VERSION_8 && dcontext->thread_record->under_dynamo_control)) { -# ifdef HOT_PATCHING_INTERFACE +# ifdef HOT_PATCHING_INTERFACE /* Don't expect to be here for -hotp_only */ ASSERT_CURIOSITY(!DYNAMO_OPTION(hotp_only)); -# endif +# endif ASSERT(dcontext->next_tag != BACK_TO_NATIVE_AFTER_SYSCALL); /* currently pc is the ret after sysenter, we need it to be the return point * (the ret after the call to the vsyscall sysenter) @@ -2036,9 +2039,9 @@ handle_system_call(dcontext_t *dcontext) *((app_pc *)get_mcontext(dcontext)->xsp) = after_do_syscall_code(dcontext); } } -#endif +# endif -#if defined(MACOS) && defined(X86) +# if defined(MACOS) && defined(X86) if (get_syscall_method() == SYSCALL_METHOD_SYSENTER && !dcontext->sys_was_int) { /* The kernel returns control to whatever user-mode places in edx. * We want to put this in even if we skip the syscall as we'll still call @@ -2049,12 +2052,12 @@ handle_system_call(dcontext_t *dcontext) dcontext->app_xdx = mc->xdx; mc->xdx = (reg_t)post_sysenter; } -#endif +# endif /* first do the pre-system-call */ if (execute_syscall && pre_system_call(dcontext)) { /* now do the actual syscall instruction */ -#ifdef UNIX +# ifdef UNIX /* XXX: move into some routine inside unix/? * if so, move #include of sys/syscall.h too */ @@ -2083,7 +2086,7 @@ handle_system_call(dcontext_t *dcontext) LOG(THREAD, LOG_SYSCALLS, 3, "for sigreturn, set sys_param1 to " PFX "\n", dcontext->sys_param1); } -#else +# else if (use_prev_dcontext) { /* get the current, but now swapped out, dcontext */ dcontext_t *tmp_dcontext = dcontext; @@ -2100,7 +2103,7 @@ handle_system_call(dcontext_t *dcontext) */ tmp_dcontext->whereami = DR_WHERE_FCACHE; } -#endif +# endif SELF_PROTECT_LOCAL(dcontext, READONLY); @@ -2108,7 +2111,7 @@ handle_system_call(dcontext_t *dcontext) KSTART_DC(dcontext, syscall_fcache); /* stopped in dispatch_exit_fcache_stats */ bool is_ignorable = ignorable_system_call(sysnum, NULL, dcontext); do { -#ifdef UNIX +# ifdef UNIX /* It is difficult to undo some pre-syscall handling, especially for * sigreturn's signal mask and clone syscalls. We go ahead and run the * syscall before we deliver the signal for all non-ignorable syscalls. @@ -2125,21 +2128,21 @@ handle_system_call(dcontext_t *dcontext) !is_ignorable); if (!is_ignorable && dcontext->signals_pending > 0) dcontext->signals_pending = -1; -#endif +# endif enter_fcache(dcontext, (fcache_enter_func_t) /* DEFAULT_ISA_MODE as we want the ISA mode of our gencode */ convert_data_to_function( PC_AS_JMP_TGT(DEFAULT_ISA_MODE, (app_pc)fcache_enter)), PC_AS_JMP_TGT(DEFAULT_ISA_MODE, do_syscall)); -#ifdef UNIX +# ifdef UNIX if (!is_ignorable && dcontext->signals_pending > 0) repeat = true; else break; -#endif +# endif } while (repeat); -#if defined(UNIX) && !defined(LINUX_KERNEL) +# if defined(UNIX) && !defined(LINUX_KERNEL) if (dcontext->signals_pending != 0) { /* i#2019: see comments in dispatch_enter_fcache() */ KSTOP(syscall_fcache); @@ -2159,7 +2162,7 @@ handle_system_call(dcontext_t *dcontext) trace_abort(dcontext); receive_pending_signal(dcontext); } else -#endif +# endif /* will handle post processing in handle_post_system_call */ ASSERT_NOT_REACHED(); } else { @@ -2170,7 +2173,7 @@ handle_system_call(dcontext_t *dcontext) if (execute_syscall) { instrument_post_syscall(dcontext, dcontext->sys_num); } -#ifdef WINDOWS +# ifdef WINDOWS if (get_syscall_method() == SYSCALL_METHOD_SYSENTER) { /* decided to skip syscall -- pop retaddr, restore sysenter storage * (if applicable) and set next target */ @@ -2186,13 +2189,14 @@ handle_system_call(dcontext_t *dcontext) */ get_mcontext(dcontext)->xsp -= XSP_SZ; } -#else +# else adjust_syscall_continuation(dcontext); set_fcache_target(dcontext, dcontext->asynch_target); -#endif +# endif } SELF_PROTECT_LOCAL(dcontext, READONLY); } +#endif static void handle_post_system_call(dcontext_t *dcontext) From d611d8d8ad2b4c82b42dfe9ce292792e83fbec10 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Sun, 7 Jun 2026 00:09:50 -0400 Subject: [PATCH 052/156] Remove unused ignorable_system_call function --- core/kernel_linux/os.c | 6 ------ core/kernel_linux/os_exports.h | 2 -- 2 files changed, 8 deletions(-) diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index 0a96fa791..bfadbe657 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -2215,12 +2215,6 @@ get_stack_bounds(dcontext_t *dcontext, byte **base, byte **top) return true; } -bool -ignorable_system_call(int num) -{ - ASSERT_NOT_PORTED(false); - return true; -} bool is_clone_thread_syscall(dcontext_t *dcontext) diff --git a/core/kernel_linux/os_exports.h b/core/kernel_linux/os_exports.h index 7ac57c020..d69871b45 100644 --- a/core/kernel_linux/os_exports.h +++ b/core/kernel_linux/os_exports.h @@ -184,8 +184,6 @@ bool is_sigreturn_syscall(dcontext_t *dcontext); bool was_sigreturn_syscall(dcontext_t *dcontext); -bool -ignorable_system_call(int num); bool kernel_is_64bit(void); From 7ca7c4c8dc593d3d1bd749300a2962cf04f03fb9 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Sun, 7 Jun 2026 00:10:26 -0400 Subject: [PATCH 053/156] Early return bb_process_syscall in kernel mode --- core/arch/interp.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/arch/interp.c b/core/arch/interp.c index a18b9efa0..9bdda0cff 100644 --- a/core/arch/interp.c +++ b/core/arch/interp.c @@ -1906,6 +1906,11 @@ bb_process_non_ignorable_syscall(dcontext_t *dcontext, build_bb_t *bb, int sysnu static inline bool bb_process_syscall(dcontext_t *dcontext, build_bb_t *bb) { +#ifdef LINUX_KERNEL + ASSERT_MESSAGE(CHKLVL_ASSERTS, "There should not be system calls in the kernel.", + false); + return true; +#endif int sysnum; /* PR 307284: for simplicity do syscall/int processing post-client. * We give up on inlining but we can still use ignorable/shared syscalls From aab389998d9ad7a0d9047de3120873c5c426efa6 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Sun, 7 Jun 2026 00:31:05 -0400 Subject: [PATCH 054/156] Exclude dead code from kernel builds --- core/dispatch.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/core/dispatch.c b/core/dispatch.c index 8026814ff..84db3c506 100644 --- a/core/dispatch.c +++ b/core/dispatch.c @@ -89,8 +89,10 @@ dispatch_exit_fcache(dcontext_t *dcontext); static void dispatch_exit_fcache_stats(dcontext_t *dcontext); +#ifndef LINUX_KERNEL static void handle_post_system_call(dcontext_t *dcontext); +#endif static void handle_special_tag(dcontext_t *dcontext); @@ -731,6 +733,7 @@ dispatch_enter_native(dcontext_t *dcontext) ASSERT_NOT_REACHED(); } +#ifndef LINUX_KERNEL static void set_next_tag_to_prior_syscall(dcontext_t *dcontext) { @@ -748,6 +751,7 @@ set_next_tag_to_prior_syscall(dcontext_t *dcontext) : FRAG_ISA_MODE(dcontext->last_fragment->flags)); ASSERT(is_syscall_at_pc(dcontext, dcontext->next_tag)); } +#endif static void dispatch_enter_dynamorio(dcontext_t *dcontext) @@ -904,8 +908,10 @@ dispatch_enter_dynamorio(dcontext_t *dcontext) KSTART_DC(dcontext, dispatch_num_exits); if (wherewasi != DR_WHERE_APP) { /* if not first entrance */ +#ifndef LINUX_KERNEL if (get_at_syscall(dcontext)) handle_post_system_call(dcontext); +#endif #ifdef X86 /* If the next basic block starts at a debug register value, @@ -2198,6 +2204,7 @@ handle_system_call(dcontext_t *dcontext) } #endif +#ifndef LINUX_KERNEL static void handle_post_system_call(dcontext_t *dcontext) { @@ -2212,7 +2219,7 @@ handle_post_system_call(dcontext_t *dcontext) /* some syscalls require modifying local memory */ SELF_PROTECT_LOCAL(dcontext, WRITABLE); -#ifdef UNIX +# ifdef UNIX /* restore mcontext values prior to invoking instrument_post_syscall() */ if (was_sigreturn_syscall(dcontext)) { /* restore app xax/r0 */ @@ -2221,16 +2228,16 @@ handle_post_system_call(dcontext_t *dcontext) dcontext->sys_param1, dcontext->asynch_target); /* XXX i#3544: Check if this is a proper register to use */ mc->IF_X86_ELSE(xax, IF_RISCV64_ELSE(a0, r0)) = dcontext->sys_param1; -# ifdef MACOS +# ifdef MACOS /* We need to skip the use app_xdx, as we've changed the context. * We can't just set app_xdx from handle_sigreturn() as the * pre-sysenter code clobbers app_xdx, and we want to handle * a failed SYS_sigreturn. */ skip_adjust = true; -# endif +# endif } -#endif +# endif /* i#1661: ensure we set the right pc for dr_get_mcontext() */ get_mcontext(dcontext)->pc = dcontext->asynch_target; @@ -2240,7 +2247,7 @@ handle_post_system_call(dcontext_t *dcontext) /* XXX: need to handle syscall failure -- those that clobbered asynch_target * need to restore it to its previous value, which has to be stored somewhere! */ -#ifdef WINDOWS +# ifdef WINDOWS if (DYNAMO_OPTION(sygate_sysenter) && get_syscall_method() == SYSCALL_METHOD_SYSENTER) { /* restore sysenter_storage, note stack was popped twice for @@ -2248,25 +2255,26 @@ handle_post_system_call(dcontext_t *dcontext) get_mcontext(dcontext)->xsp -= XSP_SZ; *((app_pc *)get_mcontext(dcontext)->xsp) = dcontext->sysenter_storage; } -#else +# else if (!skip_adjust) adjust_syscall_continuation(dcontext); -#endif +# endif set_fcache_target(dcontext, dcontext->asynch_target); -#ifdef WINDOWS +# ifdef WINDOWS /* We no longer need asynch_target so zero it out. Other pieces of DR * -- callback & APC handling, detach -- test asynch_target to determine * where the next app pc to execute is stored. If asynch_target != 0, * it holds the value, else it's in the esi slot. */ dcontext->asynch_target = 0; -#endif +# endif LOG(THREAD, LOG_SYSCALLS, 3, "finished handling system call\n"); SELF_PROTECT_LOCAL(dcontext, READONLY); /* caller will go back to couldbelinking status */ } +#endif /* !LINUX_KERNEL */ #ifdef WINDOWS /* in callback.c */ From 21734d3850132563b7fadab02f70497d7561873c Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Sun, 7 Jun 2026 08:32:11 -0400 Subject: [PATCH 055/156] Reformat code with clang-format --- core/kernel_linux/os.c | 1 - 1 file changed, 1 deletion(-) diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index bfadbe657..7cde1d757 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -2215,7 +2215,6 @@ get_stack_bounds(dcontext_t *dcontext, byte **base, byte **top) return true; } - bool is_clone_thread_syscall(dcontext_t *dcontext) { From ab63f138d832c23adf3d3313bd23f923f111975e Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Sun, 7 Jun 2026 16:31:56 -0400 Subject: [PATCH 056/156] Fix path of instrlist.o --- core/kernel_linux/modules/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/kernel_linux/modules/Makefile b/core/kernel_linux/modules/Makefile index d67686373..47bc4af18 100644 --- a/core/kernel_linux/modules/Makefile +++ b/core/kernel_linux/modules/Makefile @@ -31,7 +31,7 @@ dynamorio-objs :=\ ../../hashtable.o\ ../../heap.o\ ../../hotpatch.o\ -../../instrlist.o\ +../../ir/instrlist.o\ ../../io.o\ ../../link.o\ ../../loader_shared.o\ From 9cd519b05853b917695ff654ffb75fd5f3715188 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Sun, 7 Jun 2026 16:39:16 -0400 Subject: [PATCH 057/156] Use kernel compatible wrapper headers --- core/io.c | 2 +- core/options.c | 2 +- core/perscache.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/io.c b/core/io.c index 5c2eacb8e..be0326278 100644 --- a/core/io.c +++ b/core/io.c @@ -50,7 +50,7 @@ typedef unsigned long ulong; void dr_fpu_exception_init(void); #endif -#include /* for varargs */ +#include "stdarg_wrapper.h" /* for varargs */ #ifdef UNIX # ifdef MACOS diff --git a/core/options.c b/core/options.c index fc6833aad..c478cbbac 100644 --- a/core/options.c +++ b/core/options.c @@ -40,7 +40,7 @@ * */ -#include +#include "stddef_wrapper.h" #ifndef NOT_DYNAMORIO_CORE # include "globals.h" diff --git a/core/perscache.c b/core/perscache.c index 7c0424a56..0aa9b3975 100644 --- a/core/perscache.c +++ b/core/perscache.c @@ -48,7 +48,7 @@ #include "hotpatch.h" #include "synch.h" #include "module_shared.h" -#include /* for offsetof */ +#include "stddef_wrapper.h" /* for offsetof */ #include "instrument.h" #ifdef DEBUG From b10acb721d9d5462d8174c8be7cffefdb2cd522c Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Sun, 7 Jun 2026 16:52:27 -0400 Subject: [PATCH 058/156] Update mutex lock/unlock function names --- core/barrier.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/barrier.c b/core/barrier.c index 44a76362b..16149f291 100644 --- a/core/barrier.c +++ b/core/barrier.c @@ -17,18 +17,18 @@ bool barrier_wait(barrier_t *barrier) { int count; - mutex_lock(&barrier->lock); + d_r_mutex_lock(&barrier->lock); ASSERT(barrier->count > 0); barrier->count -= 1; count = barrier->count; - mutex_unlock(&barrier->lock); + d_r_mutex_unlock(&barrier->lock); if (count == 0) { return true; } for (;;) { - mutex_lock(&barrier->lock); + d_r_mutex_lock(&barrier->lock); count = barrier->count; - mutex_unlock(&barrier->lock); + d_r_mutex_unlock(&barrier->lock); if (count == 0) { return false; } From f92d99fa023b21e7745ea295a0cf5c1747e601c1 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Sun, 7 Jun 2026 21:45:29 -0400 Subject: [PATCH 059/156] Fix headers --- core/io.c | 2 ++ core/lib/globals_shared.h | 6 +----- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/core/io.c b/core/io.c index be0326278..b38f9cfd6 100644 --- a/core/io.c +++ b/core/io.c @@ -58,7 +58,9 @@ dr_fpu_exception_init(void); # define _EXTERNALIZE_CTYPE_INLINES_TOP_ # define _EXTERNALIZE_CTYPE_INLINES_ # endif +# ifndef LINUX_KERNEL # include +# endif #endif #ifdef NOT_DYNAMORIO_CORE_PROPER diff --git a/core/lib/globals_shared.h b/core/lib/globals_shared.h index 2ca25a0ce..1735cd985 100644 --- a/core/lib/globals_shared.h +++ b/core/lib/globals_shared.h @@ -76,11 +76,7 @@ #include "globals_api.h" // IWYU pragma: export -#ifdef LINUX_KERNEL -# include /* for USHRT_MAX */ -#else -# include /* for USHRT_MAX */ -#endif +#include "../limits_wrapper.h" /* for USHRT_MAX */ #ifdef UNIX # ifdef LINUX_KERNEL From 3d0326d44344be08df5cfe0ddb9bfbd160f82c2b Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Sun, 7 Jun 2026 23:39:45 -0400 Subject: [PATCH 060/156] Use wrapper header for limits.h in iox.h --- core/iox.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/iox.h b/core/iox.h index 90eb840bb..d5483c381 100644 --- a/core/iox.h +++ b/core/iox.h @@ -38,7 +38,7 @@ * iox.h: i/o routines for both Linux and Windows */ -#include /* for UCHAR_MAX */ +#include "limits_wrapper.h" /* for UCHAR_MAX */ #ifdef IOX_WIDE_CHAR # define TCHAR wchar_t From 3fbf118f67a68d8bf4af745a4b012618a363717f Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Sun, 7 Jun 2026 23:40:34 -0400 Subject: [PATCH 061/156] Add explicit void to kstat_calibrate in stats.c --- core/stats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/stats.c b/core/stats.c index 036cb9081..21dcc9b8b 100644 --- a/core/stats.c +++ b/core/stats.c @@ -225,7 +225,7 @@ kstat_exit() } static void -kstat_calibrate() +kstat_calibrate(void) { uint i; static bool kstats_calibrated = false; From 671c2719884b7fa74c9f0e87a78f350e5b322779 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Sun, 7 Jun 2026 23:40:57 -0400 Subject: [PATCH 062/156] Skip send_nudge_signal in kernel builds --- core/nudge.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/nudge.c b/core/nudge.c index 789e396e6..4b38a0735 100644 --- a/core/nudge.c +++ b/core/nudge.c @@ -586,10 +586,14 @@ nudge_internal(process_id_t pid, uint nudge_action_mask, uint64 client_arg, nudge_add_pending(dcontext, &nudge_arg); return DR_SUCCESS; } else { +#ifndef LINUX_KERNEL if (send_nudge_signal(pid, nudge_action_mask, client_id, client_arg)) return DR_SUCCESS; else return DR_FAILURE; +#else + return DR_FAILURE; +#endif } #endif /* WINDOWS -> UNIX */ } From 807826ee8610ab6a5421eeaa6516be45356a42c5 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 8 Jun 2026 12:21:41 -0400 Subject: [PATCH 063/156] Add explicit void to vm_areas_statistics() --- core/vmareas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/vmareas.c b/core/vmareas.c index 3b082932d..57087a617 100644 --- a/core/vmareas.c +++ b/core/vmareas.c @@ -1687,7 +1687,7 @@ vm_areas_init() } static void -vm_areas_statistics() +vm_areas_statistics(void) { #ifdef PROGRAM_SHEPHERDING DOLOG(1, LOG_VMAREAS | LOG_STATS, { From ac0235aa59898092c4979551857bbf7b0f9c2185 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 8 Jun 2026 12:22:52 -0400 Subject: [PATCH 064/156] Mark intentional fall-throughs with DR_FALLTHROUGH --- core/iox.h | 6 +++--- core/lib/globals_shared.h | 10 ++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/core/iox.h b/core/iox.h index d5483c381..8116e953f 100644 --- a/core/iox.h +++ b/core/iox.h @@ -479,7 +479,7 @@ TNAME(d_r_vsnprintf)(TCHAR *s, size_t max, const TCHAR *fmt, va_list ap) decimal, false); break; } - /* note no break */ + DR_FALLTHROUGH; case _T('x'): case _T('X'): case _T('o'): @@ -543,7 +543,7 @@ TNAME(d_r_vsnprintf)(TCHAR *s, size_t max, const TCHAR *fmt, va_list ap) str = va_arg(ap, TCHAR *); break; } - /* fall-through */ + DR_FALLTHROUGH; case _T('S'): #ifdef IOX_WIDE_CHAR h_type = true; @@ -557,7 +557,7 @@ TNAME(d_r_vsnprintf)(TCHAR *s, size_t max, const TCHAR *fmt, va_list ap) case _T('G'): if (decimal == 0 || decimal == -1) decimal = 1; /* default */ - /* no break */ + DR_FALLTHROUGH; case _T('e'): case _T('E'): case _T('f'): { diff --git a/core/lib/globals_shared.h b/core/lib/globals_shared.h index 1735cd985..a27f834dd 100644 --- a/core/lib/globals_shared.h +++ b/core/lib/globals_shared.h @@ -1114,4 +1114,14 @@ typedef struct _priv_mcontext_t { #include "mcxtx_api.h" // IWYU pragma: export } priv_mcontext_t; +#ifdef __has_attribute +# if __has_attribute(__fallthrough__) +# define DR_FALLTHROUGH __attribute__((__fallthrough__)) +# else +# define DR_FALLTHROUGH ((void)0) /* fallthrough */ +# endif +#else +# define DR_FALLTHROUGH ((void)0) /* fallthrough */ +#endif + #endif /* _GLOBALS_SHARED_H_ */ From 9da53bf31f1b0167e0bc97f0fbc221ec7c00dc93 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 8 Jun 2026 12:29:57 -0400 Subject: [PATCH 065/156] Reformat code with clang-format --- core/io.c | 2 +- core/iox.h | 2 +- core/nudge.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/io.c b/core/io.c index b38f9cfd6..f1be310e3 100644 --- a/core/io.c +++ b/core/io.c @@ -59,7 +59,7 @@ dr_fpu_exception_init(void); # define _EXTERNALIZE_CTYPE_INLINES_ # endif # ifndef LINUX_KERNEL -# include +# include # endif #endif diff --git a/core/iox.h b/core/iox.h index 8116e953f..68989d162 100644 --- a/core/iox.h +++ b/core/iox.h @@ -557,7 +557,7 @@ TNAME(d_r_vsnprintf)(TCHAR *s, size_t max, const TCHAR *fmt, va_list ap) case _T('G'): if (decimal == 0 || decimal == -1) decimal = 1; /* default */ - DR_FALLTHROUGH; + DR_FALLTHROUGH; case _T('e'): case _T('E'): case _T('f'): { diff --git a/core/nudge.c b/core/nudge.c index 4b38a0735..2358f0dfc 100644 --- a/core/nudge.c +++ b/core/nudge.c @@ -586,14 +586,14 @@ nudge_internal(process_id_t pid, uint nudge_action_mask, uint64 client_arg, nudge_add_pending(dcontext, &nudge_arg); return DR_SUCCESS; } else { -#ifndef LINUX_KERNEL +# ifndef LINUX_KERNEL if (send_nudge_signal(pid, nudge_action_mask, client_id, client_arg)) return DR_SUCCESS; else return DR_FAILURE; -#else +# else return DR_FAILURE; -#endif +# endif } #endif /* WINDOWS -> UNIX */ } From 21c4f721f334b4732d4115a95537de13ff3a89e0 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 8 Jun 2026 13:12:12 -0400 Subject: [PATCH 066/156] Add explicit void to function prototypes --- core/fcache.c | 2 +- core/heap.c | 2 +- core/options.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/fcache.c b/core/fcache.c index bab58b6d5..9fce38114 100644 --- a/core/fcache.c +++ b/core/fcache.c @@ -764,7 +764,7 @@ fcache_free_unit(dcontext_t *dcontext, fcache_unit_t *unit, bool dealloc_or_reus * options, returns true if modified the value of any options to make them * compatible. This is called while the options are writable. */ bool -fcache_check_option_compatibility() +fcache_check_option_compatibility(void) { bool ret = false; uint i; diff --git a/core/heap.c b/core/heap.c index 829ec1893..f0da68146 100644 --- a/core/heap.c +++ b/core/heap.c @@ -2209,7 +2209,7 @@ vmm_heap_fork_init(dcontext_t *dcontext) * modified the value of any options to make them compatible */ bool -heap_check_option_compatibility() +heap_check_option_compatibility(void) { bool ret = false; diff --git a/core/options.c b/core/options.c index c478cbbac..65517d119 100644 --- a/core/options.c +++ b/core/options.c @@ -2427,7 +2427,7 @@ check_option_compatibility_helper(int recurse_count) /* returns true if changed any options */ static bool -check_option_compatibility() +check_option_compatibility(void) { ASSERT_OWN_OPTIONS_LOCK(true, &options_lock); ASSERT(!OPTIONS_PROTECTED()); @@ -2436,7 +2436,7 @@ check_option_compatibility() /* returns true if changed any options */ static bool -check_dynamic_option_compatibility() +check_dynamic_option_compatibility(void) { ASSERT_OWN_OPTIONS_LOCK(true, &options_lock); /* NOTE : use non-synch form of USAGE_ERROR in here to avoid From a4c9c5726ab4478ffc1efdcbe3eb90f38920efa1 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 8 Jun 2026 13:13:40 -0400 Subject: [PATCH 067/156] Exclude double related print functions from kernel builds --- core/io.c | 2 ++ core/iox.h | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/core/io.c b/core/io.c index f1be310e3..153b464d2 100644 --- a/core/io.c +++ b/core/io.c @@ -91,6 +91,7 @@ const static double zerof = 0.0; # define neg_inf (-1.0 / zerof) #endif +#ifndef LINUX_KERNEL /* assumes that d > 0 */ long /* exported to utils.c */ double2int_trunc(double d) @@ -118,6 +119,7 @@ double2int(double d) else return i; } +#endif #ifdef WINDOWS /***************************************************************************** diff --git a/core/iox.h b/core/iox.h index 68989d162..1e78ca564 100644 --- a/core/iox.h +++ b/core/iox.h @@ -114,6 +114,7 @@ TNAME(ulong_to_str)(ulong num, int base, TCHAR *buf, int decimal, bool caps) return p; } +#ifndef LINUX_KERNEL /* N.B.: when building with /QIfist casting rounds instead of truncating (i#763)! * Thus, use double2int_trunc() instead of casting. */ @@ -272,6 +273,7 @@ TNAME(d_r_vsnprintf_float)(double val, const TCHAR *c, } return str; } +#endif /* Returns number of chars printed, not including the null terminator. * If number is larger than max, @@ -561,10 +563,15 @@ TNAME(d_r_vsnprintf)(TCHAR *s, size_t max, const TCHAR *fmt, va_list ap) case _T('e'): case _T('E'): case _T('f'): { +#ifdef LINUX_KERNEL + ASSERT_NOT_REACHED(); + str = _T("FLOATING POINT NOT SUPPORTED."); +#else /* pretty sure will always be promoted to a double in arg list */ double val = va_arg(ap, double); str = TNAME(d_r_vsnprintf_float)(val, c, prefixbuf, buf, decimal, space_flag, plus_flag, pound_flag); +#endif break; } case _T('n'): { From 0315ffad5e7a679e83c3afeeb6133066739d5f74 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 8 Jun 2026 13:15:08 -0400 Subject: [PATCH 068/156] Remove unit-rct.o from dynamorio-objs --- core/kernel_linux/modules/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/core/kernel_linux/modules/Makefile b/core/kernel_linux/modules/Makefile index 47bc4af18..b4173ea2b 100644 --- a/core/kernel_linux/modules/Makefile +++ b/core/kernel_linux/modules/Makefile @@ -45,7 +45,6 @@ dynamorio-objs :=\ ../../rct.o\ ../../stats.o\ ../../synch.o\ -../../unit-rct.o\ ../../utils.o\ ../../barrier.o\ ../../vmareas.o\ From 3463ac7e863bfa315e3bdc16ac17e0b411ed5bbe Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 10 Jun 2026 20:39:09 -0400 Subject: [PATCH 069/156] Add stub for os_wait_thread_terminated --- core/kernel_linux/os.c | 7 +++++++ core/kernel_linux/os_exports.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index 7cde1d757..570010d50 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -1689,6 +1689,13 @@ is_thread_terminated(dcontext_t *dcontext) return true; } +bool +os_wait_thread_terminated(dcontext_t *dcontext) +{ + ASSERT_NOT_PORTED(false); + return true; +} + bool thread_get_mcontext(thread_record_t *tr, dr_mcontext_t *mc) { diff --git a/core/kernel_linux/os_exports.h b/core/kernel_linux/os_exports.h index d69871b45..b402c61c4 100644 --- a/core/kernel_linux/os_exports.h +++ b/core/kernel_linux/os_exports.h @@ -88,6 +88,8 @@ thread_id_t get_sys_thread_id(void); bool is_thread_terminated(dcontext_t *dcontext); +bool +os_wait_thread_terminated(dcontext_t *dcontext); void os_tls_pre_init(int gdt_index); From dc0979a02258c6e62b1ce4ee35378f9324f6b9c0 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 10 Jun 2026 20:41:43 -0400 Subject: [PATCH 070/156] Fix headers in utils.c --- core/utils.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/core/utils.c b/core/utils.c index d75fc9e60..6753fc4c6 100644 --- a/core/utils.c +++ b/core/utils.c @@ -45,20 +45,26 @@ #include "dr_tools.h" #include "utils.h" #include "module_shared.h" -#include + +#ifndef LINUX_KERNEL +# include +#endif #ifdef PROCESS_CONTROL # include "moduledb.h" /* for process control macros */ #endif #ifdef UNIX -# include -# include -# include -# include -# include -# include -# include +# include "types_wrapper.h" +# ifndef LINUX_KERNEL +# include +# include +# include +# include +# include +# include +# include +# endif #else # include /* XXX : remove when syslog macros fixed */ @@ -73,8 +79,8 @@ # include "synch.h" /* all_threads_synch_lock */ #endif -#include /* for varargs */ -#include /* for offsetof */ +#include "stdarg_wrapper.h" /* for varargs */ +#include "stddef_wrapper.h" /* for offsetof */ try_except_t global_try_except; #ifdef UNIX From c39830aef209697c553245ca72497b9b9b7797e4 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 10 Jun 2026 20:42:43 -0400 Subject: [PATCH 071/156] Update utils.c --- core/utils.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/core/utils.c b/core/utils.c index 6753fc4c6..64f12dba1 100644 --- a/core/utils.c +++ b/core/utils.c @@ -98,7 +98,7 @@ sideline_exit(void); * performs some cleanup and then calls os_terminate */ static void -soft_terminate() +soft_terminate(void) { #ifdef SIDELINE /* kill child threads */ @@ -755,7 +755,8 @@ utils_init() ASSERT(sizeof(uint) == 4); ASSERT(sizeof(reg_t) == sizeof(void *)); -#ifdef UNIX /* after options_init(), before we open logfile or call instrument_init() */ +#if defined(UNIX) && !defined(LINUX_KERNEL) + /* after options_init(), before we open logfile or call instrument_init() */ os_file_init(); #endif @@ -1720,6 +1721,7 @@ divide_uint64_print(uint64 numerator, uint64 denominator, bool percentage, uint extern long double2int_trunc(double d); +#ifndef LINUX_KERNEL /* For printing a float. * NOTE: You must preserve x87 floating point state to call this function, unless * you can prove the compiler will never use x87 state for float operations. @@ -1748,6 +1750,7 @@ double_print(double val, uint precision, uint *top, uint *bottom, const char **s *top = double2int_trunc(val); *bottom = double2int_trunc((val - *top) * precision_multiple); } +#endif #ifdef WINDOWS /* for pre_inject, injector, and core shared files, is just wrapper for syslog @@ -3846,7 +3849,7 @@ MD5Transform(uint32 state[4], const unsigned char block[MD5_BLOCK_LENGTH]) { uint32 a, b, c, d, in[MD5_BLOCK_LENGTH / 4]; -#if BYTE_ORDER == LITTLE_ENDIAN +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ memcpy(in, block, sizeof(in)); #else for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) { From c1fd0ed264b2ed6b167d08bd8b5b8619053990be Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Thu, 11 Jun 2026 00:07:50 -0400 Subject: [PATCH 072/156] Exclude signal_remove_alarm_handlers from kernel builds --- core/synch.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/synch.c b/core/synch.c index fe423d45a..5aec9a526 100644 --- a/core/synch.c +++ b/core/synch.c @@ -2170,7 +2170,7 @@ detach_on_permanent_stack(bool internal, bool do_cleanup, dr_stats_t *drstats) wait_for_outstanding_nudges(); #endif -#ifdef UNIX +#if defined(UNIX) && !defined(LINUX_KERNEL) /* i#2270: we ignore alarm signals during detach to reduce races. */ signal_remove_alarm_handlers(my_dcontext); #endif @@ -2372,7 +2372,9 @@ detach_externally_on_new_stack(void) if (my_dcontext != NULL) enter_threadexit(my_dcontext); /* i#2270: we ignore alarm signals during detach to reduce races. */ +#ifndef LINUX_KERNEL signal_remove_alarm_handlers(my_dcontext); +#endif /* suspend all DR-controlled threads at safe locations */ if (!synch_with_all_threads(THREAD_SYNCH_SUSPENDED_VALID_MCONTEXT, &threads, &num_threads, From a9bf07bab80239a9d18a90333b54b92402571232 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Thu, 11 Jun 2026 11:51:55 -0400 Subject: [PATCH 073/156] Allocate badopt/wordbuffer on the heap in kernel build --- core/options.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/core/options.c b/core/options.c index 65517d119..ba3b576ed 100644 --- a/core/options.c +++ b/core/options.c @@ -42,6 +42,10 @@ #include "stddef_wrapper.h" +#ifdef LINUX_KERNEL +# include +#endif + #ifndef NOT_DYNAMORIO_CORE # include "globals.h" # include "fcache.h" @@ -675,9 +679,6 @@ set_dynamo_options_common(options_t *options, const char *optstr, bool for_this_ char *opt; const char *pos = optstr; bool got_badopt = false; - char badopt[MAX_OPTION_LENGTH]; - - char wordbuffer[MAX_OPTION_LENGTH]; /* used in the OPTION_COMMAND define above, declared here to save stack * space XXX : value_true and value_false could be static const if @@ -688,6 +689,21 @@ set_dynamo_options_common(options_t *options, const char *optstr, bool for_this_ if (optstr == NULL) return 0; +#ifdef LINUX_KERNEL + /* Kernel stack frames are limited to 4096 bytes; heap-allocate to avoid + * exceeding that limit with two MAX_OPTION_LENGTH buffers on the stack. */ + char *badopt = kmalloc(MAX_OPTION_LENGTH, GFP_KERNEL); + char *wordbuffer = kmalloc(MAX_OPTION_LENGTH, GFP_KERNEL); + if (badopt == NULL || wordbuffer == NULL) { + kfree(badopt); + kfree(wordbuffer); + return -1; + } +#else + char badopt[MAX_OPTION_LENGTH]; + char wordbuffer[MAX_OPTION_LENGTH]; +#endif + ASSERT_OWN_OPTIONS_LOCK(options == &dynamo_options || options == &temp_options, &options_lock); ASSERT(!OPTIONS_PROTECTED()); @@ -730,6 +746,10 @@ set_dynamo_options_common(options_t *options, const char *optstr, bool for_this_ IF_DEBUG_ELSE("Terminating", "Continuing")); } +#ifdef LINUX_KERNEL + kfree(badopt); + kfree(wordbuffer); +#endif return (int)got_badopt; } From dd28ac68082c2474fb9c7a24817c2cbbdf959c15 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Thu, 11 Jun 2026 13:00:00 -0400 Subject: [PATCH 074/156] Allocate badopt/wordbuffer as static in kernel build --- core/options.c | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/core/options.c b/core/options.c index ba3b576ed..d189d26b8 100644 --- a/core/options.c +++ b/core/options.c @@ -42,10 +42,6 @@ #include "stddef_wrapper.h" -#ifdef LINUX_KERNEL -# include -#endif - #ifndef NOT_DYNAMORIO_CORE # include "globals.h" # include "fcache.h" @@ -689,24 +685,18 @@ set_dynamo_options_common(options_t *options, const char *optstr, bool for_this_ if (optstr == NULL) return 0; + ASSERT_OWN_OPTIONS_LOCK(options == &dynamo_options || options == &temp_options, + &options_lock); + ASSERT(!OPTIONS_PROTECTED()); + #ifdef LINUX_KERNEL - /* Kernel stack frames are limited to 4096 bytes; heap-allocate to avoid - * exceeding that limit with two MAX_OPTION_LENGTH buffers on the stack. */ - char *badopt = kmalloc(MAX_OPTION_LENGTH, GFP_KERNEL); - char *wordbuffer = kmalloc(MAX_OPTION_LENGTH, GFP_KERNEL); - if (badopt == NULL || wordbuffer == NULL) { - kfree(badopt); - kfree(wordbuffer); - return -1; - } + /* Kernel stack frames are limited to 4096 bytes; use static (safe under options_lock). */ + static char badopt[MAX_OPTION_LENGTH]; + static char wordbuffer[MAX_OPTION_LENGTH]; #else char badopt[MAX_OPTION_LENGTH]; char wordbuffer[MAX_OPTION_LENGTH]; #endif - - ASSERT_OWN_OPTIONS_LOCK(options == &dynamo_options || options == &temp_options, - &options_lock); - ASSERT(!OPTIONS_PROTECTED()); while ((opt = getword(optstr, &pos, wordbuffer, sizeof(wordbuffer))) != NULL) { if (opt[0] == '-') { value = NULL; @@ -746,10 +736,6 @@ set_dynamo_options_common(options_t *options, const char *optstr, bool for_this_ IF_DEBUG_ELSE("Terminating", "Continuing")); } -#ifdef LINUX_KERNEL - kfree(badopt); - kfree(wordbuffer); -#endif return (int)got_badopt; } From e853429a2d557cabe22faefa5707529ad3f3ed84 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Thu, 11 Jun 2026 13:00:24 -0400 Subject: [PATCH 075/156] Exclude rseq related code in kernel build --- core/vmareas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/vmareas.c b/core/vmareas.c index 57087a617..81d586876 100644 --- a/core/vmareas.c +++ b/core/vmareas.c @@ -8266,7 +8266,7 @@ check_thread_vm_area(dcontext_t *dcontext, app_pc pc, app_pc tag, void **vmlist, if (stop != NULL) { *stop = area->end; ASSERT(*stop != NULL); -#ifdef LINUX +#if defined(LINUX) && !defined(LINUX_KERNEL) if (!vmvector_empty(d_r_rseq_areas)) { /* XXX i#3798: While for core operation we do not need to end a block at * an rseq endpoint, we need clients to treat the endpoint as a barrier and From 6cbe98af0a98bc52049ef902443b487ac93ccd6c Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Thu, 11 Jun 2026 13:02:21 -0400 Subject: [PATCH 076/156] Prefix atomic functions with d_r_ to avoid naming conflicts --- core/arch/arch.c | 16 ++++++++-------- core/arch/atomic_exports.h | 24 ++++++++++++------------ core/kernel_linux/os.c | 2 +- core/unix/os.c | 2 +- core/utils.c | 8 ++++---- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/core/arch/arch.c b/core/arch/arch.c index 55a5f68d9..1b3f53d79 100644 --- a/core/arch/arch.c +++ b/core/arch/arch.c @@ -4026,17 +4026,17 @@ unit_test_atomic_ops(void) ATOMIC_8BYTE_WRITE(&count3, value64, false); EXPECT(count3, -1); # endif - EXPECT(atomic_inc_and_test(&count1), true); /* result is 0 */ - EXPECT(atomic_inc_and_test(&count1), false); /* result is 1 */ - EXPECT(atomic_dec_and_test(&count1), false); /* init value is 1, result is 0 */ - EXPECT(atomic_dec_and_test(&count1), true); /* init value is 0, result is -1 */ - EXPECT(atomic_dec_becomes_zero(&count1), false); /* result is -2 */ + EXPECT(d_r_atomic_inc_and_test(&count1), true); /* result is 0 */ + EXPECT(d_r_atomic_inc_and_test(&count1), false); /* result is 1 */ + EXPECT(d_r_atomic_dec_and_test(&count1), false); /* init value is 1, result is 0 */ + EXPECT(d_r_atomic_dec_and_test(&count1), true); /* init value is 0, result is -1 */ + EXPECT(d_r_atomic_dec_becomes_zero(&count1), false); /* result is -2 */ EXPECT(atomic_compare_exchange_int(&count1, -3, 1), false); /* no exchange */ EXPECT(count1, -2); EXPECT(atomic_compare_exchange_int(&count1, -2, 1), true); /* exchange */ - EXPECT(atomic_dec_becomes_zero(&count1), true); /* result is 0 */ - EXPECT(atomic_dec_and_test(&count1), true); /* init value is 0, result is -1 */ - EXPECT(atomic_dec_and_test(&count1), true); /* init value is -1, result is -2 */ + EXPECT(d_r_atomic_dec_becomes_zero(&count1), true); /* result is 0 */ + EXPECT(d_r_atomic_dec_and_test(&count1), true); /* init value is 0, result is -1 */ + EXPECT(d_r_atomic_dec_and_test(&count1), true); /* init value is -1, result is -2 */ ATOMIC_4BYTE_WRITE(&count1, 0, false); do_parallel_updates(); EXPECT(count1, MAX_NUM_THREADS); diff --git a/core/arch/atomic_exports.h b/core/arch/atomic_exports.h index ad5cc7ee2..725a2cce7 100644 --- a/core/arch/atomic_exports.h +++ b/core/arch/atomic_exports.h @@ -195,19 +195,19 @@ /* returns true if result value is zero */ static inline bool -atomic_inc_and_test(volatile int *var) +d_r_atomic_inc_and_test(volatile int *var) { return (ATOMIC_INC(int, *(var)) == 0); } /* Returns true if result value is negative. */ static inline bool -atomic_dec_and_test(volatile int *var) +d_r_atomic_dec_and_test(volatile int *var) { return (ATOMIC_DEC(int, *(var)) < 0); } /* returns true if result value is zero */ static inline bool -atomic_dec_becomes_zero(volatile int *var) +d_r_atomic_dec_becomes_zero(volatile int *var) { return (ATOMIC_DEC(int, *(var)) == 0); } @@ -576,19 +576,19 @@ DEF_ATOMIC_incdec(ATOMIC_INC_int, int, "w", "add") DEF_ATOMIC_incdec(ATOMIC_INC_ } while (0) /* wait for interrupt */ static inline bool -atomic_inc_and_test(volatile int *var) +d_r_atomic_inc_and_test(volatile int *var) { return atomic_add_exchange_int(var, 1) == 0; } static inline bool -atomic_dec_and_test(volatile int *var) +d_r_atomic_dec_and_test(volatile int *var) { return atomic_add_exchange_int(var, -1) < 0; } static inline bool -atomic_dec_becomes_zero(volatile int *var) +d_r_atomic_dec_becomes_zero(volatile int *var) { return atomic_add_exchange_int(var, -1) == 0; } @@ -1050,19 +1050,19 @@ atomic_exchange_int(volatile int *var, int newval) # define SPINLOCK_PAUSE() __asm__ __volatile__(".int 0x0100000F"); static inline bool -atomic_inc_and_test(volatile int *var) +d_r_atomic_inc_and_test(volatile int *var) { return atomic_add_exchange_int(var, 1) == 0; } static inline bool -atomic_dec_and_test(volatile int *var) +d_r_atomic_dec_and_test(volatile int *var) { return atomic_add_exchange_int(var, -1) < 0; } static inline bool -atomic_dec_becomes_zero(volatile int *var) +d_r_atomic_dec_becomes_zero(volatile int *var) { return atomic_add_exchange_int(var, -1) == 0; } @@ -1085,7 +1085,7 @@ atomic_dec_becomes_zero(volatile int *var) * Returns true if the resulting value is zero, otherwise returns false */ static inline bool -atomic_inc_and_test(volatile int *var) +d_r_atomic_inc_and_test(volatile int *var) { bool is_zero; ATOMIC_INC_int_nowzero(*var, is_zero); @@ -1096,7 +1096,7 @@ atomic_inc_and_test(volatile int *var) * Returns true if the result is negative, otherwise returns false. */ static inline bool -atomic_dec_and_test(volatile int *var) +d_r_atomic_dec_and_test(volatile int *var) { bool is_negative; ATOMIC_DEC_int_nowneg(*var, is_negative); @@ -1107,7 +1107,7 @@ atomic_dec_and_test(volatile int *var) * Returns true if the resulting value is zero, otherwise returns false. */ static inline bool -atomic_dec_becomes_zero(volatile int *var) +d_r_atomic_dec_becomes_zero(volatile int *var) { bool is_zero; ATOMIC_DEC_int_nowzero(*var, is_zero); diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index 570010d50..2aeefec07 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -2305,7 +2305,7 @@ mutex_wait_contended_lock(mutex_t *lock) * If we do use a true wait need to set client_thread_safe_for_synch around it */ /* we now have to undo our earlier request */ - atomic_dec_and_test(&lock->lock_requests); + d_r_atomic_dec_and_test(&lock->lock_requests); while (!mutex_trylock(lock)) { #ifdef CLIENT_INTERFACE diff --git a/core/unix/os.c b/core/unix/os.c index b50b97226..162a51086 100644 --- a/core/unix/os.c +++ b/core/unix/os.c @@ -10684,7 +10684,7 @@ mutex_wait_contended_lock(mutex_t *lock, priv_mcontext_t *mc) } } else { /* we now have to undo our earlier request */ - atomic_dec_and_test(&lock->lock_requests); + d_r_atomic_dec_and_test(&lock->lock_requests); while (!d_r_mutex_trylock(lock)) { if (set_client_safe_for_synch) diff --git a/core/utils.c b/core/utils.c index 64f12dba1..bb2c251a4 100644 --- a/core/utils.c +++ b/core/utils.c @@ -885,7 +885,7 @@ d_r_mutex_lock_app(mutex_t *lock, priv_mcontext_t *mc) } /* we have strong intentions to grab this lock, increment requests */ - acquired = atomic_inc_and_test(&lock->lock_requests); + acquired = d_r_atomic_inc_and_test(&lock->lock_requests); DEADLOCK_AVOIDANCE_LOCK(lock, acquired, ownable); if (!acquired) { @@ -936,7 +936,7 @@ d_r_mutex_unlock(mutex_t *lock) ASSERT(lock->lock_requests > LOCK_FREE_STATE && "lock not owned"); DEADLOCK_AVOIDANCE_UNLOCK(lock, ownable); - if (atomic_dec_and_test(&lock->lock_requests)) + if (d_r_atomic_dec_and_test(&lock->lock_requests)) return; /* if we were not the last one to hold the lock, (i.e. final value is not LOCK_FREE_STATE) @@ -1192,7 +1192,7 @@ d_r_read_lock(read_write_lock_t *rw) /* no need to pause */ } /* Even if we didn't wait another reader may be waiting for notification */ - if (!atomic_dec_becomes_zero(&rw->num_pending_readers)) { + if (!d_r_atomic_dec_becomes_zero(&rw->num_pending_readers)) { /* If we were not the last pending reader, we need to notify another waiting one so that it can get out of the contention path. @@ -1302,7 +1302,7 @@ d_r_read_unlock(read_write_lock_t *rw) to check if the writer is in fact waiting. Even though this is not atomic we don't need to loop here - d_r_write_lock() will loop. */ - if (atomic_dec_becomes_zero(&rw->num_readers)) { + if (d_r_atomic_dec_becomes_zero(&rw->num_readers)) { /* if the writer is waiting it definitely needs to hold the mutex */ if (mutex_testlock(&rw->lock)) { /* test that it was not this thread owning both write and read lock */ From 305a9c174c2a7f1afe0e123817d9b1d643cf8f50 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Thu, 11 Jun 2026 13:04:31 -0400 Subject: [PATCH 077/156] Exclude old_basedir in kernel build --- core/utils.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/utils.c b/core/utils.c index bb2c251a4..cd217b1a3 100644 --- a/core/utils.c +++ b/core/utils.c @@ -2655,7 +2655,9 @@ static bool basedir_initialized = false; /* below used in the create_log_dir function to avoid having it on the stack * on what is a critical path for stack depth (diagnostics->create_log_dir-> * get_parameter */ +#ifndef LINUX_KERNEL static char old_basedir[MAXIMUM_PATH]; +#endif /* this lock is recursive because current implementation recurses to create the * basedir when called to create the logdir before the basedir is created, is * also useful in case we receive an exception in the create_log_dir function From b20b78a92c0d8a396e0ffa4ec3e5e42488fa5b11 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Thu, 11 Jun 2026 13:04:50 -0400 Subject: [PATCH 078/156] Exclude os_signal_thread_detach/os_wait_thread_detached --- core/synch.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/core/synch.c b/core/synch.c index 5aec9a526..055ed35fe 100644 --- a/core/synch.c +++ b/core/synch.c @@ -2272,7 +2272,7 @@ detach_on_permanent_stack(bool internal, bool do_cleanup, dr_stats_t *drstats) * the thread_initexit_lock is held so that we can clean up thread * data later. */ -#ifdef UNIX +#if defined(UNIX) && !defined(LINUX_KERNEL) os_signal_thread_detach(threads[i]->dcontext); #endif LOG(GLOBAL, LOG_ALL, 1, "Detach: thread " TIDFMT " is being resumed as native\n", @@ -2281,7 +2281,7 @@ detach_on_permanent_stack(bool internal, bool do_cleanup, dr_stats_t *drstats) } ASSERT(my_idx != -1 || !internal); -#ifdef UNIX +#if defined(UNIX) && !defined(LINUX_KERNEL) LOG(GLOBAL, LOG_ALL, 1, "Detach: waiting for threads to fully detach\n"); for (i = 0; i < num_threads; i++) { if (i != my_idx && !IS_CLIENT_THREAD(threads[i]->dcontext)) @@ -2437,16 +2437,20 @@ detach_externally_on_new_stack(void) * the thread_initexit_lock is held so that we can clean up thread * data later. */ +#ifndef LINUX_KERNEL os_signal_thread_detach(threads[i]->dcontext); +#endif LOG(GLOBAL, LOG_ALL, 1, "Detach: thread " TIDFMT " is being resumed as native\n", threads[i]->id); os_thread_resume(threads[i]); } +#ifndef LINUX_KERNEL LOG(GLOBAL, LOG_ALL, 1, "Detach: waiting for threads to fully detach\n"); for (i = 0; i < num_threads; i++) { if (i != my_idx && !IS_CLIENT_THREAD(threads[i]->dcontext)) os_wait_thread_detached(threads[i]->dcontext); } +#endif /* Clean up each thread now that everyone has gone native. Needs to be * done with the thread_initexit_lock held, which is true within a synched * region. From 63b5e84fadb2ecba598920befb570d4646916031 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Thu, 11 Jun 2026 21:07:28 -0400 Subject: [PATCH 079/156] Update dynamorio.o object paths to match current DynamoRIO layout --- core/kernel_linux/modules/Makefile | 39 ++++++++++++++---------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/core/kernel_linux/modules/Makefile b/core/kernel_linux/modules/Makefile index b4173ea2b..e0bd6f23f 100644 --- a/core/kernel_linux/modules/Makefile +++ b/core/kernel_linux/modules/Makefile @@ -48,28 +48,25 @@ dynamorio-objs :=\ ../../utils.o\ ../../barrier.o\ ../../vmareas.o\ -../../x86/arch.o\ -../../x86/decode.o\ -../../x86/decode_fast.o\ -../../x86/decode_table.o\ -../../x86/disassemble.o\ -../../x86/emit_utils.o\ -../../x86/encode.o\ -../../x86/instr.o\ -../../x86/instrument.o\ -../../x86/interp.o\ -../../x86/loadtoconst.o\ -../../x86/mangle.o\ -../../x86/optimize.o\ -../../x86/proc.o\ -../../x86/retcheck.o\ -../../x86/sideline.o\ -../../x86/steal_reg.o\ -../../x86/x86_code.o\ -../../x86/asm_defines.o\ -../../x86/x86.o\ +../../arch/arch.o\ +../../ir/x86/decode.o\ +../../ir/x86/decode_fast.o\ +../../ir/x86/decode_table.o\ +../../ir/x86/disassemble.o\ +../../arch/x86/emit_utils.o\ +../../ir/x86/encode.o\ +../../ir/x86/instr.o\ +../../lib/instrument.o\ +../../arch/interp.o\ +../../arch/loadtoconst.o\ +../../arch/x86/mangle.o\ +../../arch/x86/optimize.o\ +../../arch/x86/proc.o\ +../../arch/retcheck.o\ +../../arch/sideline.o\ +../../arch/asm_defines.o\ +../../arch/x86/x86.o\ ../../kernel_linux/os.o\ -../../kernel_linux/hypercall_guest.o\ ../../kernel_linux/page_table.o\ ../../kernel_linux/kernel_interface.o\ ../../kernel_linux/dynamorio_module_interface.o\ From 82afa3437dfd66745f195a0c1fac46ee147da909 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Sun, 14 Jun 2026 16:50:03 -0400 Subject: [PATCH 080/156] Remove hypercall related headers --- core/kernel_linux/os.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index 2aeefec07..5e7773af0 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -1,6 +1,4 @@ #include "globals.h" -#include "hypercall.h" -#include "hypercall_guest.h" #include "kernel_interface.h" #include "module_shared.h" #include "page_table.h" From ea0213ca393160dc3a894369e8aaa4ab0bc27614 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Sun, 14 Jun 2026 16:50:47 -0400 Subject: [PATCH 081/156] Add explicit void to function prototypes --- core/arch/interp.c | 4 ++-- core/kernel_linux/os.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/arch/interp.c b/core/arch/interp.c index 9bdda0cff..a0e3a846a 100644 --- a/core/arch/interp.c +++ b/core/arch/interp.c @@ -129,7 +129,7 @@ DECLARE_NEVERPROT_VAR(uint debug_bb_count, 0); /* initialization */ void -interp_init() +interp_init(void) { if (INTERNAL_OPTION(bbdump_tags)) { bbdump_file = open_log_file("bbs", NULL, 0); @@ -146,7 +146,7 @@ static int num_rets_removed; /* cleanup */ void -interp_exit() +interp_exit(void) { if (INTERNAL_OPTION(bbdump_tags)) { close_log_file(bbdump_file); diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index 5e7773af0..f8121802c 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -1648,7 +1648,7 @@ os_heap_get_commit_limit(size_t *commit_used, size_t *commit_limit) } void -thread_yield() +thread_yield(void) { SPINLOCK_PAUSE(); } From a144310286122c26838081ac47edfaac39b72560 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Sun, 14 Jun 2026 16:53:00 -0400 Subject: [PATCH 082/156] Add d_r_ prefix to mutex functions --- core/kernel_linux/os.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index f8121802c..72d67f5c0 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -2305,7 +2305,7 @@ mutex_wait_contended_lock(mutex_t *lock) /* we now have to undo our earlier request */ d_r_atomic_dec_and_test(&lock->lock_requests); - while (!mutex_trylock(lock)) { + while (!d_r_mutex_trylock(lock)) { #ifdef CLIENT_INTERFACE if (dcontext != NULL && IS_CLIENT_THREAD(dcontext) && (mutex_t *)dcontext->client_data->client_grab_mutex == lock) @@ -2396,21 +2396,21 @@ destroy_event(event_t e) void signal_event(event_t e) { - mutex_lock(&e->lock); + d_r_mutex_lock(&e->lock); e->signaled = true; LOG(THREAD_GET, LOG_THREADS, 3, "thread %d signalling event " PFX "\n", get_thread_id(), e); - mutex_unlock(&e->lock); + d_r_mutex_unlock(&e->lock); } void reset_event(event_t e) { - mutex_lock(&e->lock); + d_r_mutex_lock(&e->lock); e->signaled = false; LOG(THREAD_GET, LOG_THREADS, 3, "thread %d resetting event " PFX "\n", get_thread_id(), e); - mutex_unlock(&e->lock); + d_r_mutex_unlock(&e->lock); } /* FIXME: compare use and implementation with man pthread_cond_wait */ @@ -2426,16 +2426,16 @@ wait_for_event(event_t e) e); while (true) { if (e->signaled) { - mutex_lock(&e->lock); + d_r_mutex_lock(&e->lock); if (!e->signaled) { /* some other thread beat us to it */ LOG(THREAD, LOG_THREADS, 3, "thread %d was beaten to event " PFX "\n", get_thread_id(), e); - mutex_unlock(&e->lock); + d_r_mutex_unlock(&e->lock); } else { /* reset the event */ e->signaled = false; - mutex_unlock(&e->lock); + d_r_mutex_unlock(&e->lock); LOG(THREAD, LOG_THREADS, 3, "thread %d finished waiting for event " PFX "\n", get_thread_id(), e); return; From 4b5eeb97422fea86b13c045a0accf443a6f34011 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Sun, 14 Jun 2026 16:54:59 -0400 Subject: [PATCH 083/156] Update function signatures in core/kernel_linux/os.c --- core/kernel_linux/os.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index 72d67f5c0..35b74a721 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -1695,14 +1695,14 @@ os_wait_thread_terminated(dcontext_t *dcontext) } bool -thread_get_mcontext(thread_record_t *tr, dr_mcontext_t *mc) +thread_get_mcontext(thread_record_t *tr, priv_mcontext_t *mc) { ASSERT_NOT_PORTED(false); return true; } bool -thread_set_mcontext(thread_record_t *tr, dr_mcontext_t *mc) +thread_set_mcontext(thread_record_t *tr, priv_mcontext_t *mc) { ASSERT_NOT_PORTED(false); return true; @@ -2612,13 +2612,13 @@ signal_thread_inherit(dcontext_t *dcontext, void *clone_record) } void -thread_set_self_context(void *cxt) +thread_set_self_context(void *cxt, bool is_detach_external) { ASSERT_NOT_PORTED(false); } void -thread_set_self_mcontext(dr_mcontext_t *mc) +thread_set_self_mcontext(priv_mcontext_t *mc, bool is_detach_external) { ASSERT_NOT_PORTED(false); } @@ -2637,7 +2637,7 @@ receive_pending_signal(dcontext_t *dcontext) } void -os_forge_exception(app_pc target_pc, exception_type_t type) +os_forge_exception(app_pc target_pc, dr_exception_type_t type) { ASSERT_NOT_PORTED(false); } From 08bc42f30785eba11cb7d2befb3de5e83679eb93 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Sun, 14 Jun 2026 17:01:58 -0400 Subject: [PATCH 084/156] Rename fallthrough variable in interp.c to avoid kernel macro collision --- core/arch/interp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/arch/interp.c b/core/arch/interp.c index a0e3a846a..57c5279db 100644 --- a/core/arch/interp.c +++ b/core/arch/interp.c @@ -6911,7 +6911,7 @@ mangle_trace(dcontext_t *dcontext, instrlist_t *ilist, monitor_data_t *md) { instr_t *inst, *next_inst, *start_instr, *jmp; uint blk, num_exits_deleted; - app_pc fallthrough = NULL; + app_pc fallthrough_pc = NULL; bool found_syscall = false, found_int = false; /* We don't assert that mangle_trace_at_end() is true b/c the client @@ -6979,7 +6979,7 @@ mangle_trace(dcontext_t *dcontext, instrlist_t *ilist, monitor_data_t *md) /* Do not call instr_length() on this inst: use length * of translation! (i#509) */ - fallthrough = decode_next_pc(dcontext, xl8); + fallthrough_pc = decode_next_pc(dcontext, xl8); } /* PR 299808: identify bb boundaries. We can't go by translations alone, as @@ -7061,7 +7061,7 @@ mangle_trace(dcontext_t *dcontext, instrlist_t *ilist, monitor_data_t *md) return false; } /* must have been no final exit cti: add final fall-through jmp */ - jmp = create_exit_jmp(dcontext, fallthrough, fallthrough, 0); + jmp = create_exit_jmp(dcontext, fallthrough_pc, fallthrough_pc, 0); /* XXX PR 307284: support client modifying, replacing, or adding * syscalls and ints: need to re-analyze. Then we wouldn't * need the md->final_exit_flags field anymore. From 0cb76cc3f8424717f2197092b40e10b8bcb9489e Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Sun, 14 Jun 2026 19:36:54 -0400 Subject: [PATCH 085/156] Reformat code with clang-format --- core/arch/arch.c | 12 ++++++------ core/options.c | 3 ++- core/synch.c | 14 +++++++------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/core/arch/arch.c b/core/arch/arch.c index 1b3f53d79..f7b9ac72f 100644 --- a/core/arch/arch.c +++ b/core/arch/arch.c @@ -4026,15 +4026,15 @@ unit_test_atomic_ops(void) ATOMIC_8BYTE_WRITE(&count3, value64, false); EXPECT(count3, -1); # endif - EXPECT(d_r_atomic_inc_and_test(&count1), true); /* result is 0 */ - EXPECT(d_r_atomic_inc_and_test(&count1), false); /* result is 1 */ - EXPECT(d_r_atomic_dec_and_test(&count1), false); /* init value is 1, result is 0 */ - EXPECT(d_r_atomic_dec_and_test(&count1), true); /* init value is 0, result is -1 */ - EXPECT(d_r_atomic_dec_becomes_zero(&count1), false); /* result is -2 */ + EXPECT(d_r_atomic_inc_and_test(&count1), true); /* result is 0 */ + EXPECT(d_r_atomic_inc_and_test(&count1), false); /* result is 1 */ + EXPECT(d_r_atomic_dec_and_test(&count1), false); /* init value is 1, result is 0 */ + EXPECT(d_r_atomic_dec_and_test(&count1), true); /* init value is 0, result is -1 */ + EXPECT(d_r_atomic_dec_becomes_zero(&count1), false); /* result is -2 */ EXPECT(atomic_compare_exchange_int(&count1, -3, 1), false); /* no exchange */ EXPECT(count1, -2); EXPECT(atomic_compare_exchange_int(&count1, -2, 1), true); /* exchange */ - EXPECT(d_r_atomic_dec_becomes_zero(&count1), true); /* result is 0 */ + EXPECT(d_r_atomic_dec_becomes_zero(&count1), true); /* result is 0 */ EXPECT(d_r_atomic_dec_and_test(&count1), true); /* init value is 0, result is -1 */ EXPECT(d_r_atomic_dec_and_test(&count1), true); /* init value is -1, result is -2 */ ATOMIC_4BYTE_WRITE(&count1, 0, false); diff --git a/core/options.c b/core/options.c index d189d26b8..c9a6ebaa1 100644 --- a/core/options.c +++ b/core/options.c @@ -690,7 +690,8 @@ set_dynamo_options_common(options_t *options, const char *optstr, bool for_this_ ASSERT(!OPTIONS_PROTECTED()); #ifdef LINUX_KERNEL - /* Kernel stack frames are limited to 4096 bytes; use static (safe under options_lock). */ + /* Kernel stack frames are limited to 4096 bytes; use static (safe under + * options_lock). */ static char badopt[MAX_OPTION_LENGTH]; static char wordbuffer[MAX_OPTION_LENGTH]; #else diff --git a/core/synch.c b/core/synch.c index 055ed35fe..c55f4f2b0 100644 --- a/core/synch.c +++ b/core/synch.c @@ -2371,10 +2371,10 @@ detach_externally_on_new_stack(void) /* synch with flush */ if (my_dcontext != NULL) enter_threadexit(my_dcontext); - /* i#2270: we ignore alarm signals during detach to reduce races. */ -#ifndef LINUX_KERNEL + /* i#2270: we ignore alarm signals during detach to reduce races. */ +# ifndef LINUX_KERNEL signal_remove_alarm_handlers(my_dcontext); -#endif +# endif /* suspend all DR-controlled threads at safe locations */ if (!synch_with_all_threads(THREAD_SYNCH_SUSPENDED_VALID_MCONTEXT, &threads, &num_threads, @@ -2437,20 +2437,20 @@ detach_externally_on_new_stack(void) * the thread_initexit_lock is held so that we can clean up thread * data later. */ -#ifndef LINUX_KERNEL +# ifndef LINUX_KERNEL os_signal_thread_detach(threads[i]->dcontext); -#endif +# endif LOG(GLOBAL, LOG_ALL, 1, "Detach: thread " TIDFMT " is being resumed as native\n", threads[i]->id); os_thread_resume(threads[i]); } -#ifndef LINUX_KERNEL +# ifndef LINUX_KERNEL LOG(GLOBAL, LOG_ALL, 1, "Detach: waiting for threads to fully detach\n"); for (i = 0; i < num_threads; i++) { if (i != my_idx && !IS_CLIENT_THREAD(threads[i]->dcontext)) os_wait_thread_detached(threads[i]->dcontext); } -#endif +# endif /* Clean up each thread now that everyone has gone native. Needs to be * done with the thread_initexit_lock held, which is true within a synched * region. From 008bb41b942ee0ba9d3d97a73bfb6fe5722b2b93 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Sun, 14 Jun 2026 22:00:24 -0400 Subject: [PATCH 086/156] Mark intentional fall throughs with the DR_FALLTHROUGH macro --- core/ir/x86/decode.c | 4 ++-- core/ir/x86/decode_fast.c | 6 +++--- core/ir/x86/disassemble.c | 5 ++++- core/ir/x86/encode.c | 4 ++-- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/core/ir/x86/decode.c b/core/ir/x86/decode.c index 06acaaea5..eff5bb13d 100644 --- a/core/ir/x86/decode.c +++ b/core/ir/x86/decode.c @@ -1989,7 +1989,7 @@ decode_operand(decode_info_t *di, byte optype, opnd_size_t opsize, opnd_t *opnd) /* ensure referencing memory */ if (di->mod >= 3) return false; - /* fall through */ + DR_FALLTHROUGH; case TYPE_E: case TYPE_Q: case TYPE_W: return decode_modrm(di, optype, opsize, NULL, opnd); @@ -2187,7 +2187,7 @@ decode_operand(decode_info_t *di, byte optype, opnd_size_t opsize, opnd_t *opnd) if (di->mod != 3) { return decode_modrm(di, optype, opsize, NULL, opnd); } - /* fall through*/ + DR_FALLTHROUGH; } case TYPE_K_MODRM_R: { /* part of AVX-512: modrm.rm selects opmask register */ diff --git a/core/ir/x86/decode_fast.c b/core/ir/x86/decode_fast.c index 7f34a7629..093ba8b41 100644 --- a/core/ir/x86/decode_fast.c +++ b/core/ir/x86/decode_fast.c @@ -513,7 +513,7 @@ decode_sizeof_ex(void *drcontext, byte *start_pc, int *num_prefixes, uint *rip_r case REPNE_PREFIX_OPCODE: case REP_PREFIX_OPCODE: /* REP */ rep_prefix = true; - /* fall through */ + DR_FALLTHROUGH; case RAW_PREFIX_lock: /* LOCK */ case CS_SEG_OPCODE: /* segment overrides */ case DS_SEG_OPCODE: @@ -535,7 +535,7 @@ decode_sizeof_ex(void *drcontext, byte *start_pc, int *num_prefixes, uint *rip_r if (X64_MODE_DC(dcontext) || TEST(0x10, *(pc + 1))) { evex_prefix = true; } - /* Fall-through is deliberate, EVEX is handled through VEX below */ + DR_FALLTHROUGH; } case VEX_3BYTE_PREFIX_OPCODE: case VEX_2BYTE_PREFIX_OPCODE: { @@ -1367,7 +1367,7 @@ decode_cti(void *drcontext, byte *pc, instr_t *instr) break; case EVEX_PREFIX_OPCODE: instr_set_prefix_flag(instr, PREFIX_EVEX); - /* fall-through */ + DR_FALLTHROUGH; case VEX_3BYTE_PREFIX_OPCODE: { /* EVEX and VEX 3-byte prefixes imply instruction opcodes by encoding mm * bits in the second prefix byte. In theory, there are 5 VEX mm bits, but diff --git a/core/ir/x86/disassemble.c b/core/ir/x86/disassemble.c index 3ba7b7267..b5c529a77 100644 --- a/core/ir/x86/disassemble.c +++ b/core/ir/x86/disassemble.c @@ -172,7 +172,7 @@ opnd_disassemble_noimplicit(char *buf, size_t bufsz, size_t *sofar DR_PARAM_INOU /* if has implicit st0 then don't print it */ (opnd_get_reg(opnd) == REG_ST0 && instr_memory_reference_size(instr) > 0)) return false; - /* else fall through */ + DR_FALLTHROUGH; case TYPE_A: case TYPE_B: case TYPE_C: @@ -225,6 +225,7 @@ opnd_disassemble_noimplicit(char *buf, size_t bufsz, size_t *sofar DR_PARAM_INOU reg_disassemble(buf, bufsz, sofar, opnd_get_segment(opnd), 0, "", ""); return true; } + DR_FALLTHROUGH; case TYPE_Y: case TYPE_FLOATCONST: case TYPE_XREG: @@ -333,6 +334,7 @@ instr_opcode_name_suffix(instr_t *instr) else if (sz == 8) return "q"; } + DR_FALLTHROUGH; case OP_pusha: case OP_popa: { uint sz = instr_memory_reference_size(instr); @@ -341,6 +343,7 @@ instr_opcode_name_suffix(instr_t *instr) else if (sz == 32) return "d"; } + DR_FALLTHROUGH; case OP_iret: { uint sz = instr_memory_reference_size(instr); if (sz == 6) diff --git a/core/ir/x86/encode.c b/core/ir/x86/encode.c index 290ac4ce3..795164167 100644 --- a/core/ir/x86/encode.c +++ b/core/ir/x86/encode.c @@ -1562,7 +1562,7 @@ opnd_type_ok(decode_info_t *di /*prefixes field is IN/OUT; x86_mode is IN*/, opn if (!reg_is_strictly_zmm(opnd_get_index(opnd))) return false; } - /* fall through */ + DR_FALLTHROUGH; case TYPE_FLOATMEM: case TYPE_M: return mem_size_ok(di, opnd, optype, opsize); case TYPE_E: @@ -1801,7 +1801,7 @@ opnd_type_ok(decode_info_t *di /*prefixes field is IN/OUT; x86_mode is IN*/, opn case TYPE_K_MODRM: if (mem_size_ok(di, opnd, optype, opsize)) return true; - /* fall through */ + DR_FALLTHROUGH; case TYPE_K_MODRM_R: /* Same comment above. */ return (opnd_is_reg(opnd) && reg_is_opmask(opnd_get_reg(opnd))); From ceaa0373d1847e965c051aa9d54615511d2434f0 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Sun, 14 Jun 2026 22:09:38 -0400 Subject: [PATCH 087/156] Resolve -Wundef --- core/ir/x86/encode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/ir/x86/encode.c b/core/ir/x86/encode.c index 795164167..1fcf093df 100644 --- a/core/ir/x86/encode.c +++ b/core/ir/x86/encode.c @@ -3523,7 +3523,7 @@ instr_encode_arch(dcontext_t *dcontext, instr_t *instr, byte *copy_pc, byte *fin instr_set_rip_rel_pos(instr, (byte)(disp_relativize_at - di.start_pc)); } -#if DEBUG_DISABLE /* turn back on if want to debug */ +#ifdef DEBUG_DISABLE /* turn back on if want to debug */ if (d_r_stats->loglevel >= 3) { byte *pc = cache_pc; LOG(THREAD, LOG_EMIT, 3, "instr_encode on: "); From aefac1dcf8117540104747f05c7cb7d07dc33222 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 15 Jun 2026 17:41:47 -0400 Subject: [PATCH 088/156] Reformat DR_FALLTHROUGH --- core/ir/x86/decode_fast.c | 4 +--- core/ir/x86/disassemble.c | 6 ++++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/ir/x86/decode_fast.c b/core/ir/x86/decode_fast.c index 093ba8b41..fbfd5ba72 100644 --- a/core/ir/x86/decode_fast.c +++ b/core/ir/x86/decode_fast.c @@ -511,9 +511,7 @@ decode_sizeof_ex(void *drcontext, byte *start_pc, int *num_prefixes, uint *rip_r sz += 1; break; case REPNE_PREFIX_OPCODE: - case REP_PREFIX_OPCODE: /* REP */ - rep_prefix = true; - DR_FALLTHROUGH; + case REP_PREFIX_OPCODE: /* REP */ rep_prefix = true; DR_FALLTHROUGH; case RAW_PREFIX_lock: /* LOCK */ case CS_SEG_OPCODE: /* segment overrides */ case DS_SEG_OPCODE: diff --git a/core/ir/x86/disassemble.c b/core/ir/x86/disassemble.c index b5c529a77..a1340cbff 100644 --- a/core/ir/x86/disassemble.c +++ b/core/ir/x86/disassemble.c @@ -333,8 +333,9 @@ instr_opcode_name_suffix(instr_t *instr) return "d"; else if (sz == 8) return "q"; + + DR_FALLTHROUGH; } - DR_FALLTHROUGH; case OP_pusha: case OP_popa: { uint sz = instr_memory_reference_size(instr); @@ -342,8 +343,9 @@ instr_opcode_name_suffix(instr_t *instr) return "w"; else if (sz == 32) return "d"; + + DR_FALLTHROUGH; } - DR_FALLTHROUGH; case OP_iret: { uint sz = instr_memory_reference_size(instr); if (sz == 6) From 74475816b64faf3061364c8232c23bda7b2b324d Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 15 Jun 2026 17:48:35 -0400 Subject: [PATCH 089/156] Remvoe hypercall related code in kernel_interface.c --- core/kernel_linux/kernel_interface.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/core/kernel_linux/kernel_interface.c b/core/kernel_linux/kernel_interface.c index f727b0c5e..ded554af3 100644 --- a/core/kernel_linux/kernel_interface.c +++ b/core/kernel_linux/kernel_interface.c @@ -12,7 +12,6 @@ #include "dynamorio_module_interface.h" #include "dynamorio_module_assert_interface.h" #include "kernel_interface.h" -#include "hypercall_guest.h" #include "page_table.h" /* Used by kernel_find_dynamorio_module_bounds. */ @@ -167,11 +166,6 @@ kernel_module_init(size_t dr_heap_size) kallsyms_lookup_name_ptr = (void *)kp.addr; unregister_kprobe(&kp); -#ifdef HYPERCALL_DEBUGGING - if (!hypercall_init()) { - return false; - } -#endif /* Some OS interfaces, such as get_thread_private_dcontext, rely on the TLS * initially being all 0. */ zero_cpu_private_data(); From 9d0ba07bd33555281348643904cbeb08220c204c Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 15 Jun 2026 17:59:29 -0400 Subject: [PATCH 090/156] Fix headers for kernel build --- core/arch/x86/mangle.c | 2 +- core/lib/instrument.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/arch/x86/mangle.c b/core/arch/x86/mangle.c index 5032c877b..f14504809 100644 --- a/core/arch/x86/mangle.c +++ b/core/arch/x86/mangle.c @@ -58,7 +58,7 @@ # include "../rct.h" /* rct_add_rip_rel_addr */ #endif -#ifdef UNIX +#if defined(UNIX) && !defined(LINUX_KERNEL) # include #endif diff --git a/core/lib/instrument.c b/core/lib/instrument.c index 3d1993747..ded466b0e 100644 --- a/core/lib/instrument.c +++ b/core/lib/instrument.c @@ -54,9 +54,9 @@ #include "../fcache.h" #include "../emit.h" #include "../link.h" -#include "../monitor.h" /* for mark_trace_head */ -#include /* for varargs */ -#include "../nudge.h" /* for nudge_internal() */ +#include "../monitor.h" /* for mark_trace_head */ +#include "stdarg_wrapper.h" /* for varargs */ +#include "../nudge.h" /* for nudge_internal() */ #include "../synch.h" #include "../annotations.h" #include "../translate.h" From 3305ff4175c26efc540aaf348fe86f6e6f95eeb6 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 15 Jun 2026 18:22:09 -0400 Subject: [PATCH 091/156] Add DR_PARAM_ prefix to IN/OUT/INOUT --- core/kernel_linux/os.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index 35b74a721..bffee4edd 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -204,7 +204,8 @@ os_module_area_reset(module_area_t *ma HEAPACCT(which_heap_t which)) } generic_func_t -get_proc_address_ex(module_handle_t lib, const char *name, bool *is_indirect_code OUT) +get_proc_address_ex(module_handle_t lib, const char *name, + bool *is_indirect_code DR_PARAM_OUT) { ASSERT_NOT_PORTED(false); return 0; @@ -491,7 +492,7 @@ os_tls_exit(local_state_t *local_state, bool other_thread) } bool -os_tls_calloc(OUT uint *offset, uint num_slots, uint alignment) +os_tls_calloc(DR_PARAM_OUT uint *offset, uint num_slots, uint alignment) { ASSERT_NOT_PORTED(false); return true; @@ -1756,8 +1757,8 @@ shared_library_error(char *buf, int maxlen) } bool -shared_library_bounds(IN shlib_handle_t lib, IN byte *addr, OUT byte **start, - OUT byte **end) +shared_library_bounds(DR_PARAM_IN shlib_handle_t lib, DR_PARAM_IN byte *addr, + DR_PARAM_OUT byte **start, DR_PARAM_OUT byte **end) { return kernel_shared_library_bounds(lib, addr, start, end); } @@ -1953,7 +1954,7 @@ os_delete_mapped_file(const char *filename) } byte * -os_map_file(file_t f, size_t *size INOUT, uint64 offs, app_pc addr, uint prot, +os_map_file(file_t f, size_t *size DR_PARAM_INOUT, uint64 offs, app_pc addr, uint prot, bool copy_on_write, bool image, bool fixed) { ASSERT_NOT_PORTED(false); @@ -2098,7 +2099,7 @@ vm_region_prot(const vm_region_t *region) } bool -query_memory_ex_from_os(const byte *pc, OUT dr_mem_info_t *info) +query_memory_ex_from_os(const byte *pc, DR_PARAM_OUT dr_mem_info_t *info) { vm_region_t region; /* TODO(peter): page_table_get_region is way too slow. For now, just get the @@ -2553,7 +2554,7 @@ os_check_option_compatibility(void) } void -report_diagnostics(IN const char *message, IN const char *name, +report_diagnostics(DR_PARAM_IN const char *message, DR_PARAM_IN const char *name, security_violation_t violation_type) { /* Not implemented in the original Linux version. */ From b5207a6e86785990e3a8d28ff58d062e42ac2893 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 22 Jun 2026 18:18:43 +0000 Subject: [PATCH 092/156] Fix include path in instrument.c --- core/lib/instrument.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/lib/instrument.c b/core/lib/instrument.c index ded466b0e..f2edf5585 100644 --- a/core/lib/instrument.c +++ b/core/lib/instrument.c @@ -54,9 +54,9 @@ #include "../fcache.h" #include "../emit.h" #include "../link.h" -#include "../monitor.h" /* for mark_trace_head */ -#include "stdarg_wrapper.h" /* for varargs */ -#include "../nudge.h" /* for nudge_internal() */ +#include "../monitor.h" /* for mark_trace_head */ +#include "../stdarg_wrapper.h" /* for varargs */ +#include "../nudge.h" /* for nudge_internal() */ #include "../synch.h" #include "../annotations.h" #include "../translate.h" From 20188d175f38f26f5669a4d637d3efde19b980ef Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 22 Jun 2026 19:10:29 +0000 Subject: [PATCH 093/156] Exclude user space headers in kernel build --- core/lib/instrument.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/lib/instrument.c b/core/lib/instrument.c index f2edf5585..39c2837f7 100644 --- a/core/lib/instrument.c +++ b/core/lib/instrument.c @@ -60,7 +60,7 @@ #include "../synch.h" #include "../annotations.h" #include "../translate.h" -#ifdef UNIX +#if defined(UNIX) && !defined(LINUX_KERNEL) # include /* ITIMER_* */ # include "../unix/module.h" /* redirect_* functions */ #endif @@ -7742,7 +7742,7 @@ dr_prepopulate_cache(app_pc *tags, size_t tags_count) /* There could be duplicates if sthg was deleted and re-added during profiling */ fragment_t coarse_f; fragment_t *f; -#ifdef UNIX +#if defined(UNIX) && !defined(LINUX_KERNEL) /* We silently skip DR-segment-reading addresses to help out a caller * who sampled and couldn't avoid self-sampling for decoding. */ From 485abf75f05373b774fcbe23ab048c227dd2f786 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 22 Jun 2026 20:32:55 +0000 Subject: [PATCH 094/156] Add explicit void --- core/arch/arch.c | 2 +- core/lib/instrument.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/arch/arch.c b/core/arch/arch.c index f7b9ac72f..c7215ff78 100644 --- a/core/arch/arch.c +++ b/core/arch/arch.c @@ -2881,7 +2881,7 @@ get_global_do_syscall_entry() /* used only by cleanup_and_terminate to avoid the sysenter * sygate hack version */ byte * -get_cleanup_and_terminate_global_do_syscall_entry() +get_cleanup_and_terminate_global_do_syscall_entry(void) { /* see note above: for 32-bit linux apps we use int. * xref PR 332427 as well where sysenter causes a crash diff --git a/core/lib/instrument.c b/core/lib/instrument.c index 39c2837f7..8a73d1feb 100644 --- a/core/lib/instrument.c +++ b/core/lib/instrument.c @@ -853,7 +853,7 @@ free_callback_list(callback_list_t *vec) } static void -free_all_callback_lists() +free_all_callback_lists(void) { free_callback_list(&exit_callbacks); free_callback_list(&post_attach_callbacks); @@ -907,7 +907,7 @@ instrument_exit_event(void) /* support dr_get_mcontext() from the exit event */ if (!standalone_library) get_thread_private_dcontext()->client_data->mcontext_in_dcontext = true; - call_all(exit_callbacks, int (*)(), + call_all(exit_callbacks, int (*)(void), /* It seems the compiler is confused if we pass no var args * to the call_all macro. Bogus NULL arg */ NULL); @@ -916,13 +916,13 @@ instrument_exit_event(void) void instrument_post_attach_event(void) { - call_all(post_attach_callbacks, int (*)(), NULL); + call_all(post_attach_callbacks, int (*)(void), NULL); } void instrument_pre_detach_event(void) { - call_all(pre_detach_callbacks, int (*)(), NULL); + call_all(pre_detach_callbacks, int (*)(void), NULL); } void From 7c1f19230d9fe19975ca2323328c9d95b07fdd70 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 22 Jun 2026 20:34:02 +0000 Subject: [PATCH 095/156] Add explicit conversion --- core/ir/x86/instr.c | 2 +- core/lib/instrument.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/ir/x86/instr.c b/core/ir/x86/instr.c index 72578ce4a..51d1ee68a 100644 --- a/core/ir/x86/instr.c +++ b/core/ir/x86/instr.c @@ -1652,7 +1652,7 @@ instr_predicate_triggered(instr_t *instr, dr_mcontext_t *mc) ptr_int_t val; if (!d_r_safe_read(opnd_compute_address(src, mc), MIN(opnd_get_size(src), sizeof(val)), &val)) - return false; + return (dr_pred_trigger_t)false; return (val != 0) ? DR_PRED_TRIGGER_MATCH : DR_PRED_TRIGGER_MISMATCH; } else CLIENT_ASSERT(false, "invalid predicate/instr combo"); diff --git a/core/lib/instrument.c b/core/lib/instrument.c index 8a73d1feb..376b4ce39 100644 --- a/core/lib/instrument.c +++ b/core/lib/instrument.c @@ -1421,13 +1421,13 @@ dr_nudge_client_ex(process_id_t process_id, client_id_t client_id, uint64 argume if (client_libs[i].id == client_id) { if (client_libs[i].nudge_callbacks.num == 0) { CLIENT_ASSERT(false, "dr_nudge_client: no nudge handler registered"); - return false; + return (dr_config_status_t)false; } return nudge_internal(process_id, NUDGE_GENERIC(client), argument, client_id, timeout_ms); } } - return false; + return (dr_config_status_t)false; } else { return nudge_internal(process_id, NUDGE_GENERIC(client), argument, client_id, timeout_ms); @@ -1529,7 +1529,7 @@ instrument_fork_init(dcontext_t *dcontext) void instrument_low_on_memory(void) { - call_all(low_on_memory_callbacks, int (*)()); + call_all(low_on_memory_callbacks, int (*)(void)); } /* PR 536058: split the exit event from thread cleanup, to provide a From 795413688d049399678d31575bd500e801710863 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 22 Jun 2026 21:07:12 +0000 Subject: [PATCH 096/156] Handle -Werror=return-type in get_interrupted_location() --- core/kernel_linux/os.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index bffee4edd..4b7ed3f02 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -714,6 +714,8 @@ get_interrupted_location(dcontext_t *dcontext, interrupt_stack_frame_t *frame) return INTERRUPTED_DYNAMORIO; } } + ASSERT_NOT_REACHED(); + return INTERRUPTED_DYNAMORIO; } bool From 2e85ff89435bc1bbcafad3dacd95968c799923eb Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 22 Jun 2026 21:24:11 +0000 Subject: [PATCH 097/156] Rename INTN_LENGTH to INT_LENGTH --- core/kernel_linux/os.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index 4b7ed3f02..5e24207f2 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -139,7 +139,7 @@ typedef struct { int num_patches; cache_pc patch_pc[MAX_NUM_PATCHES]; - byte patch_buffer[MAX_NUM_PATCHES][INTN_LENGTH]; + byte patch_buffer[MAX_NUM_PATCHES][INT_LENGTH]; #ifdef DEBUG /* Keep track of where the interrupt came from for debugging. */ interrupted_location_t interrupted_location; @@ -780,7 +780,7 @@ is_patch_interrupt(os_thread_data_t *ostd, interrupt_context_t *interrupt) * all classified as "traps" rather than "faults" (see Section 6.5 in * Intel's Programmer Reference Manual, volume 3A). */ - if (ostd->patch_pc[i] + INTN_LENGTH == interrupt->frame.xip) { + if (ostd->patch_pc[i] + INT_LENGTH == interrupt->frame.xip) { return true; } second_patch(); @@ -1158,8 +1158,8 @@ handle_interrupt(interrupt_stack_frame_t *frame, dr_mcontext_t *mcontext, if (is_patch_interrupt(ostd, &interrupt)) { unpatch_fragments(dcontext, ostd); - interrupt.raw_frame->xip -= INTN_LENGTH; - interrupt.frame.xip -= INTN_LENGTH; + interrupt.raw_frame->xip -= INT_LENGTH; + interrupt.frame.xip -= INT_LENGTH; interrupt.raw_frame->xflags |= EFLAGS_IF; interrupt.frame.xflags |= EFLAGS_IF; } From 7d0cdf6dca294fe90227fd17552b3f6e756deb3e Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 22 Jun 2026 21:35:22 +0000 Subject: [PATCH 098/156] Rename fallthrough to avoid naming conflict with the kernel --- core/lib/instrument.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/lib/instrument.c b/core/lib/instrument.c index 376b4ce39..5a9af6aa7 100644 --- a/core/lib/instrument.c +++ b/core/lib/instrument.c @@ -6212,10 +6212,10 @@ dr_insert_cbr_instrumentation_help(void *drcontext, instrlist_t *ilist, instr_t app_flags_ok = instr_get_prev(instr); if (has_fallthrough) { - ptr_uint_t fallthrough = address + instr_length(drcontext, instr); + ptr_uint_t fallthrough_addr = address + instr_length(drcontext, instr); CLIENT_ASSERT(!opnd_uses_reg(user_data, DR_REG_XBX), "register ebx should not be used"); - CLIENT_ASSERT(fallthrough > address, "wrong fallthrough address"); + CLIENT_ASSERT(fallthrough_addr > address, "wrong fallthrough address"); dr_insert_clean_call_ex( drcontext, ilist, instr, callee, /* Many users will ask for mcontexts; some will set; it doesn't seem worth @@ -6228,7 +6228,7 @@ dr_insert_cbr_instrumentation_help(void *drcontext, instrlist_t *ilist, instr_t /* target is 2nd parameter */ OPND_CREATE_INTPTR(target), /* fall-throug is 3rd parameter */ - OPND_CREATE_INTPTR(fallthrough), + OPND_CREATE_INTPTR(fallthrough_addr), /* branch direction (put in ebx below) is 4th parameter */ opnd_create_reg(REG_XBX), /* user defined data is 5th parameter */ @@ -6514,8 +6514,8 @@ dr_insert_cbr_instrumentation_help(void *drcontext, instrlist_t *ilist, instr_t } if (has_fallthrough) { - ptr_uint_t fallthrough = address + instr_length(drcontext, instr); - CLIENT_ASSERT(fallthrough > address, "wrong fallthrough address"); + ptr_uint_t fallthrough_addr = address + instr_length(drcontext, instr); + CLIENT_ASSERT(fallthrough_addr > address, "wrong fallthrough address"); dr_insert_clean_call_ex( drcontext, ilist, instr, callee, /* Many users will ask for mcontexts; some will set; it doesn't seem worth @@ -6528,7 +6528,7 @@ dr_insert_cbr_instrumentation_help(void *drcontext, instrlist_t *ilist, instr_t /* Target is 2nd parameter. */ OPND_CREATE_INTPTR(target), /* Fall-through is 3rd parameter. */ - OPND_CREATE_INTPTR(fallthrough), + OPND_CREATE_INTPTR(fallthrough_addr), /* Branch direction is 4th parameter. */ opnd_create_reg(dir), /* User defined data is 5th parameter. */ From b0338419dfa3afa63ec85b28b7f65a4735d57b3f Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 22 Jun 2026 22:00:56 +0000 Subject: [PATCH 099/156] Remove redundant NULL arguments --- core/lib/instrument.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/core/lib/instrument.c b/core/lib/instrument.c index 5a9af6aa7..3eb84bb9c 100644 --- a/core/lib/instrument.c +++ b/core/lib/instrument.c @@ -907,22 +907,19 @@ instrument_exit_event(void) /* support dr_get_mcontext() from the exit event */ if (!standalone_library) get_thread_private_dcontext()->client_data->mcontext_in_dcontext = true; - call_all(exit_callbacks, int (*)(void), - /* It seems the compiler is confused if we pass no var args - * to the call_all macro. Bogus NULL arg */ - NULL); + call_all(exit_callbacks, int (*)(void)); } void instrument_post_attach_event(void) { - call_all(post_attach_callbacks, int (*)(void), NULL); + call_all(post_attach_callbacks, int (*)(void)); } void instrument_pre_detach_event(void) { - call_all(pre_detach_callbacks, int (*)(void), NULL); + call_all(pre_detach_callbacks, int (*)(void)); } void @@ -1421,13 +1418,13 @@ dr_nudge_client_ex(process_id_t process_id, client_id_t client_id, uint64 argume if (client_libs[i].id == client_id) { if (client_libs[i].nudge_callbacks.num == 0) { CLIENT_ASSERT(false, "dr_nudge_client: no nudge handler registered"); - return (dr_config_status_t)false; + return (dr_config_status_t) false; } return nudge_internal(process_id, NUDGE_GENERIC(client), argument, client_id, timeout_ms); } } - return (dr_config_status_t)false; + return (dr_config_status_t) false; } else { return nudge_internal(process_id, NUDGE_GENERIC(client), argument, client_id, timeout_ms); From 502afad4bb63861e7fc49e217a882b4d1fa47b73 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 22 Jun 2026 22:06:23 +0000 Subject: [PATCH 100/156] Remove CLIENT_INTERFACE define --- core/kernel_linux/os.c | 35 +++-------------------------------- 1 file changed, 3 insertions(+), 32 deletions(-) diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index 5e24207f2..a0a15d4e8 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -16,9 +16,7 @@ #include "cr.h" #include "monitor.h" -#ifdef CLIENT_INTERFACE -# include "instrument.h" -#endif +#include "instrument.h" /* For inline ASM. */ #ifdef X64 @@ -88,10 +86,8 @@ typedef enum { INTERRUPTED_FRAGMENT, INTERRUPTED_GENCODE, INTERRUPTED_DYNAMORIO, -#ifdef CLIENT_INTERFACE INTERRUPTED_CLIENT_LIB, INTERRUPTED_CLIENT_GENCODE, -#endif } interrupted_location_t; typedef struct { @@ -164,9 +160,7 @@ typedef struct { typedef struct os_local_state_t { local_state_extended_t state; struct os_local_state_t *self; -#ifdef CLIENT_INTERFACE void *client_tls[MAX_NUM_CLIENT_TLS]; -#endif } os_local_state_t; /* Offsets from the GS segment. */ @@ -637,18 +631,12 @@ get_interrupted_location(dcontext_t *dcontext, interrupt_stack_frame_t *frame) * kernel entry gencode, then interrupts are disabled and we * shouldn't trigger exceptions). Hence it's safe to call in_fcache. */ -#ifdef CLIENT_INTERFACE if (in_fcache(pc)) { -#else - ASSERT(in_fcache(pc)); -#endif return INTERRUPTED_FRAGMENT; -#ifdef CLIENT_INTERFACE } else { ASSERT(is_dynamo_address(frame->xip)); return INTERRUPTED_CLIENT_GENCODE; } -#endif } else { /* At this point, we could be * - in some DR code that uses exceptions (e.g., TRY..EXCEPT) @@ -668,11 +656,9 @@ get_interrupted_location(dcontext_t *dcontext, interrupt_stack_frame_t *frame) */ if (is_in_dynamo_dll(pc)) { return INTERRUPTED_DYNAMORIO; -#ifdef CLIENT_INTERFACE } else if (is_in_client_lib(pc)) { /* clean callee */ return INTERRUPTED_CLIENT_LIB; -#endif } else { /* Could either be in clean call preparation or a crashing clean * call argument. If we're in the kernel code, then in_fcache @@ -701,10 +687,8 @@ get_interrupted_location(dcontext_t *dcontext, interrupt_stack_frame_t *frame) */ ASSERT_NOT_REACHED(); return INTERRUPTED_GENCODE; -#ifdef CLIENT_INTERFACE } else if (is_in_client_lib(pc)) { return INTERRUPTED_CLIENT_LIB; -#endif } else { /* If we're in kernel code called by DynamoRIO, then we're screwed * because interrupts should be disabled and we don't know how to @@ -1069,7 +1053,6 @@ handle_kernel_interrupt(dcontext_t *dcontext, interrupt_context_t *interrupt) ASSERT_NOT_REACHED(); os_terminate(dcontext, TERMINATE_PROCESS); break; -#ifdef CLIENT_INTERFACE case INTERRUPTED_CLIENT_LIB: case INTERRUPTED_CLIENT_GENCODE: /* The client should have handled this interrupt and either suppressed @@ -1078,7 +1061,6 @@ handle_kernel_interrupt(dcontext_t *dcontext, interrupt_context_t *interrupt) ASSERT_NOT_REACHED(); os_terminate(dcontext, TERMINATE_PROCESS); break; -#endif default: os_terminate(dcontext, TERMINATE_PROCESS); } } @@ -1088,7 +1070,6 @@ nmi_handler(void) { } -#ifdef CLIENT_INTERFACE static bool send_interrupt_to_client(dcontext_t *dcontext, interrupt_context_t *interrupt) { @@ -1101,7 +1082,6 @@ send_interrupt_to_client(dcontext_t *dcontext, interrupt_context_t *interrupt) res = instrument_interrupt(dcontext, &dr_interrupt); return res; } -#endif static void handle_interrupt(interrupt_stack_frame_t *frame, dr_mcontext_t *mcontext, @@ -1164,9 +1144,7 @@ handle_interrupt(interrupt_stack_frame_t *frame, dr_mcontext_t *mcontext, interrupt.frame.xflags |= EFLAGS_IF; } -#ifdef CLIENT_INTERFACE if (send_interrupt_to_client(dcontext, &interrupt)) { -#endif #ifdef DEBUG DOKSTATS({ kstat_stack_t *ks = &dcontext->thread_kstats->stack_kstats; @@ -1212,9 +1190,7 @@ handle_interrupt(interrupt_stack_frame_t *frame, dr_mcontext_t *mcontext, /* If this returns, then we iret to whatever was interrupted. The * state in mcontext and frame are restored. */ } -#ifdef CLIENT_INTERFACE } -#endif if (local) SELF_PROTECT_LOCAL(dcontext, READONLY); @@ -1233,8 +1209,7 @@ optimize_syscall_entry(dcontext_t *dcontext) os_thread_data_t *ostd = (os_thread_data_t *)dcontext->os_field; fragment_t *f; f = build_basic_block_fragment(dcontext, (byte *)ostd->native_state.msr_lstar, - FRAG_CANNOT_DELETE, true, - true _IF_CLIENT(false) _IF_CLIENT(NULL)); + FRAG_CANNOT_DELETE, true, true, false, NULL); ostd->syscall_entry_frag = f; optimize_syscall_code(dcontext, f); } @@ -2299,7 +2274,7 @@ deadlock_avoidance_unlock(mutex_t *lock, bool ownable); void mutex_wait_contended_lock(mutex_t *lock) { - IF_CLIENT_INTERFACE(dcontext_t *dcontext = get_thread_private_dcontext();) + dcontext_t *dcontext = get_thread_private_dcontext(); /* FIXME: we don't actually use system calls to synchronize on Linux, * one day we would use futex(2) on this path (PR 295561). * For now we use a busy-wait lock. @@ -2309,17 +2284,13 @@ mutex_wait_contended_lock(mutex_t *lock) d_r_atomic_dec_and_test(&lock->lock_requests); while (!d_r_mutex_trylock(lock)) { -#ifdef CLIENT_INTERFACE if (dcontext != NULL && IS_CLIENT_THREAD(dcontext) && (mutex_t *)dcontext->client_data->client_grab_mutex == lock) dcontext->client_data->client_thread_safe_for_synch = true; -#endif thread_yield(); -#ifdef CLIENT_INTERFACE if (dcontext != NULL && IS_CLIENT_THREAD(dcontext) && (mutex_t *)dcontext->client_data->client_grab_mutex == lock) dcontext->client_data->client_thread_safe_for_synch = false; -#endif } #ifdef DEADLOCK_AVOIDANCE From 51c37941c1e04c27019008583897b4b6cc289249 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 22 Jun 2026 22:08:01 +0000 Subject: [PATCH 101/156] Reformat code --- core/ir/x86/instr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/ir/x86/instr.c b/core/ir/x86/instr.c index 51d1ee68a..ad4c063c2 100644 --- a/core/ir/x86/instr.c +++ b/core/ir/x86/instr.c @@ -1652,7 +1652,7 @@ instr_predicate_triggered(instr_t *instr, dr_mcontext_t *mc) ptr_int_t val; if (!d_r_safe_read(opnd_compute_address(src, mc), MIN(opnd_get_size(src), sizeof(val)), &val)) - return (dr_pred_trigger_t)false; + return (dr_pred_trigger_t) false; return (val != 0) ? DR_PRED_TRIGGER_MATCH : DR_PRED_TRIGGER_MISMATCH; } else CLIENT_ASSERT(false, "invalid predicate/instr combo"); From 94fa0ef5f94ccda315d5cbeea4d4ae97b2090e9b Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 22 Jun 2026 22:40:13 +0000 Subject: [PATCH 102/156] Added vsyscall_sysenter_displaced_pc in drk --- core/kernel_linux/os.c | 3 ++- core/kernel_linux/os_exports.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index a0a15d4e8..957ec9601 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -31,9 +31,10 @@ # define ASM_XSP "esp" #endif +app_pc vsyscall_page_start = NULL; app_pc vsyscall_syscall_end_pc = NULL; app_pc vsyscall_sysenter_return_pc = NULL; -app_pc vsyscall_page_start = NULL; +app_pc vsyscall_sysenter_displaced_pc = NULL; DR_API file_t our_stdin = 0; DR_API file_t our_stdout = 1; diff --git a/core/kernel_linux/os_exports.h b/core/kernel_linux/os_exports.h index b402c61c4..f4eedcf2a 100644 --- a/core/kernel_linux/os_exports.h +++ b/core/kernel_linux/os_exports.h @@ -176,6 +176,8 @@ extern app_pc vsyscall_page_start; extern app_pc vsyscall_syscall_end_pc; /* pc where kernel returns control after sysenter vsyscall */ extern app_pc vsyscall_sysenter_return_pc; +/* pc where our hook-displaced code was copied */ +extern app_pc vsyscall_sysenter_displaced_pc; #define VSYSCALL_PAGE_MAPS_NAME "[vdso]" bool From c0e578bc5dc56ed92f79b251a00a47cfbff7da38 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 22 Jun 2026 22:55:24 +0000 Subject: [PATCH 103/156] Update signature for set_itimer_callback in drk --- core/kernel_linux/os.c | 3 ++- core/kernel_linux/os_exports.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index 957ec9601..e5724a451 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -2626,7 +2626,8 @@ os_dump_core(const char *msg) bool set_itimer_callback(dcontext_t *dcontext, int which, uint millisec, - void (*func)(dcontext_t *, dr_mcontext_t *)) + void (*func)(dcontext_t *, priv_mcontext_t *), + void (*func_api)(dcontext_t *, dr_mcontext_t *)) { ASSERT_NOT_PORTED(false); return true; diff --git a/core/kernel_linux/os_exports.h b/core/kernel_linux/os_exports.h index f4eedcf2a..d463add54 100644 --- a/core/kernel_linux/os_exports.h +++ b/core/kernel_linux/os_exports.h @@ -286,7 +286,8 @@ signal_fork_init(dcontext_t *dcontext); bool set_itimer_callback(dcontext_t *dcontext, int which, uint millisec, - void (*func)(dcontext_t *, dr_mcontext_t *)); + void (*func)(dcontext_t *, priv_mcontext_t *), + void (*func_api)(dcontext_t *, dr_mcontext_t *)); uint get_itimer_frequency(dcontext_t *dcontext, int which); From c96d8b49eedfa5baf20a056a894ff58579ae045f Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 22 Jun 2026 23:17:00 +0000 Subject: [PATCH 104/156] Exclude os_module_update_dynamic_info from kernel build --- core/lib/instrument.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/lib/instrument.c b/core/lib/instrument.c index 3eb84bb9c..379e22d8c 100644 --- a/core/lib/instrument.c +++ b/core/lib/instrument.c @@ -1990,7 +1990,7 @@ instrument_module_load_trigger(app_pc pc) if (ma != NULL && !TEST(MODULE_LOAD_EVENT, ma->flags)) { /* switch to write lock */ os_get_module_info_unlock(); -#ifdef LINUX +#if defined(LINUX) && !defined(LINUX_KERNEL) /* i#3385: re-try to initialize dynamic information, because * it failed during the first flat-mmap that loaded the module. * We don't perform this if there are no clients, assuming From e3edecae4951ded7eb18a5c0cd36d3f66453fdb0 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 22 Jun 2026 23:41:16 +0000 Subject: [PATCH 105/156] Exclude rseq related code from kernel build --- core/arch/interp.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/core/arch/interp.c b/core/arch/interp.c index 57c5279db..001b71210 100644 --- a/core/arch/interp.c +++ b/core/arch/interp.c @@ -2755,7 +2755,7 @@ client_process_bb(dcontext_t *dcontext, build_bb_t *bb) /* DrMem#1735: pass app pc, not selfmod copy pc */ app_pc tag = bb->pretend_pc == NULL ? bb->start_pc : bb->pretend_pc; -#ifdef LINUX +#if defined(LINUX) && !defined(LINUX_KERNEL) if (TEST(FRAG_STARTS_RSEQ_REGION, bb->flags)) { rseq_insert_start_label(dcontext, tag, bb->ilist); /* This is a temporary flag, as it overlaps with another used later. */ @@ -3291,17 +3291,19 @@ build_bb_ilist(dcontext_t *dcontext, build_bb_t *bb) /* to split riprel, need to decode every instr */ /* in x86_to_x64, need to translate every x86 instr */ IF_X64(|| DYNAMO_OPTION(coarse_split_riprel) || DYNAMO_OPTION(x86_to_x64)) || - INTERNAL_OPTION(full_decode) - /* We separate rseq regions into their own blocks to make this check easier. */ - IF_LINUX(|| - (!vmvector_empty(d_r_rseq_areas) && - vmvector_overlap(d_r_rseq_areas, bb->start_pc, bb->start_pc + 1)))) + INTERNAL_OPTION(full_decode)) { bb->full_decode = true; - else { -#ifdef CHECK_RETURNS_SSE2 + } +#if defined(LINUX) && !defined(LINUX_KERNEL) + /* We separate rseq regions into their own blocks to make this check easier. */ + if (!vmvector_empty(d_r_rseq_areas) && + vmvector_overlap(d_r_rseq_areas, bb->start_pc, bb->start_pc + 1)) { bb->full_decode = true; -#endif } +#endif +#ifdef CHECK_RETURNS_SSE2 + bb->full_decode = true; +#endif LOG(THREAD, LOG_INTERP, 3, "\ninterp%s: ", IF_X86_64_ELSE(X64_MODE_DC(dcontext) ? "" : " (x86 mode)", "")); From bf942012d0750dc4524a68c54e11e039a0924d30 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 22 Jun 2026 23:55:17 +0000 Subject: [PATCH 106/156] Exclude PLT interception logic from kernel build --- core/arch/interp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/arch/interp.c b/core/arch/interp.c index 001b71210..2d77dc8a7 100644 --- a/core/arch/interp.c +++ b/core/arch/interp.c @@ -4041,7 +4041,7 @@ build_bb_ilist(dcontext_t *dcontext, build_bb_t *bb) return; } } -#ifdef UNIX +#if defined(UNIX) && !defined(LINUX_KERNEL) /* XXX: i#1247: After a call to a native module throught plt, DR * loses control of the app b/c of _dl_runtime_resolve */ From f1ffb91f42c60235fcedb91fc150191bea86f1c3 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 23 Jun 2026 00:20:52 +0000 Subject: [PATCH 107/156] Exclude is_currently_on_sigaltstack from kernel build --- core/lib/instrument.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/lib/instrument.c b/core/lib/instrument.c index 379e22d8c..bb9e02a10 100644 --- a/core/lib/instrument.c +++ b/core/lib/instrument.c @@ -2518,7 +2518,10 @@ dr_exit_process(int exit_code) } #endif if (!is_currently_on_dstack(dcontext) - IF_UNIX(&&!is_currently_on_sigaltstack(dcontext))) { +#if defined(UNIX) && !defined(LINUX_KERNEL) + && !is_currently_on_sigaltstack(dcontext) +#endif + ) { /* if on app stack or sigaltstack, avoid incorrect leak assert at exit */ SELF_UNPROTECT_DATASEC(DATASEC_RARELY_PROT); dr_api_exit = true; From b892c980ed8cf205373fdbb4926df8739f3e3f87 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 22 Jun 2026 23:59:30 -0700 Subject: [PATCH 108/156] Fix bb_process_syscall kernel build error --- core/arch/interp.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/core/arch/interp.c b/core/arch/interp.c index 2d77dc8a7..8d1c01ac1 100644 --- a/core/arch/interp.c +++ b/core/arch/interp.c @@ -1910,7 +1910,7 @@ bb_process_syscall(dcontext_t *dcontext, build_bb_t *bb) ASSERT_MESSAGE(CHKLVL_ASSERTS, "There should not be system calls in the kernel.", false); return true; -#endif +#else int sysnum; /* PR 307284: for simplicity do syscall/int processing post-client. * We give up on inlining but we can still use ignorable/shared syscalls @@ -1918,12 +1918,12 @@ bb_process_syscall(dcontext_t *dcontext, build_bb_t *bb) */ if (bb->pass_to_client && !bb->post_client) return false; -#ifdef DGC_DIAGNOSTICS +# ifdef DGC_DIAGNOSTICS if (TEST(FRAG_DYNGEN, bb->flags) && !is_dyngen_vsyscall(bb->instr_start)) { LOG(THREAD, LOG_INTERP, 1, "WARNING: syscall @ " PFX " in dyngen code!\n", bb->instr_start); } -#endif +# endif BBPRINT(bb, 4, "interp: syscall @ " PFX "\n", bb->instr_start); check_syscall_method(dcontext, bb->instr); bb->flags |= FRAG_HAS_SYSCALL; @@ -1931,7 +1931,7 @@ bb_process_syscall(dcontext_t *dcontext, build_bb_t *bb) * we let bb keep going, else we end bb and flag it */ sysnum = find_syscall_num(dcontext, bb->ilist, bb->instr); -#ifdef VMX86_SERVER +# ifdef VMX86_SERVER DOSTATS({ if (instr_get_opcode(bb->instr) == OP_int && instr_get_interrupt_number(bb->instr) == VMKUW_SYSCALL_GATEWAY) { @@ -1939,14 +1939,14 @@ bb_process_syscall(dcontext_t *dcontext, build_bb_t *bb) LOG(THREAD, LOG_SYSCALLS, 2, "vmkuw system call site: #=%d\n", sysnum); } }); -#endif +# endif BBPRINT(bb, 3, "syscall # is %d\n", sysnum); if (sysnum != -1 && instrument_filter_syscall(dcontext, sysnum)) { BBPRINT(bb, 3, "client asking to intercept => pretending syscall # %d is -1\n", sysnum); sysnum = -1; } -#ifdef ARM +# ifdef ARM if (sysnum != -1 && instr_is_predicated(bb->instr)) { BBPRINT(bb, 3, "conditional system calls cannot be inlined => " @@ -1954,17 +1954,17 @@ bb_process_syscall(dcontext_t *dcontext, build_bb_t *bb) sysnum); sysnum = -1; } -#endif +# endif if (sysnum != -1 && DYNAMO_OPTION(ignore_syscalls) && ignorable_system_call(sysnum, bb->instr, NULL) -#ifdef X86 +# ifdef X86 /* PR 288101: On Linux we do not yet support inlined sysenter instrs as we * do not have in-cache support for the post-sysenter continuation: we rely * for now on very simple sysenter handling where d_r_dispatch uses asynch_target * to know where to go next. */ IF_LINUX(&&instr_get_opcode(bb->instr) != OP_sysenter) -#endif /* X86 */ +# endif /* X86 */ ) { bool continue_bb; @@ -1975,16 +1975,17 @@ bb_process_syscall(dcontext_t *dcontext, build_bb_t *bb) return continue_bb; } } -#ifdef WINDOWS +# ifdef WINDOWS if (sysnum != -1 && DYNAMO_OPTION(shared_syscalls) && optimizable_system_call(sysnum)) { bb_process_shared_syscall(dcontext, bb, sysnum); return false; } -#endif +# endif /* Fall thru and handle as a non-ignorable syscall. */ return bb_process_non_ignorable_syscall(dcontext, bb, sysnum); +#endif } /* Case 3922: for wow64 we treat "call *fs:0xc0" as a system call. From 1a7da5734278a07f026e83458a5eedef59cbcb45 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 23 Jun 2026 00:17:43 -0700 Subject: [PATCH 109/156] Exclude unused functions from kernel build --- core/arch/interp.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/core/arch/interp.c b/core/arch/interp.c index 8d1c01ac1..652998f54 100644 --- a/core/arch/interp.c +++ b/core/arch/interp.c @@ -1647,6 +1647,7 @@ bb_process_mov_seg(dcontext_t *dcontext, build_bb_t *bb) } #endif /* UNIX && X86 */ +#ifndef LINUX_KERNEL /* Returns true to indicate that ignorable syscall processing is completed * with *continue_bb indicating if the bb should be continued or not. * When returning false, continue_bb isn't pertinent. @@ -1657,7 +1658,7 @@ bb_process_ignorable_syscall(dcontext_t *dcontext, build_bb_t *bb, int sysnum, { STATS_INC(ignorable_syscalls); BBPRINT(bb, 3, "found ignorable system call 0x%04x\n", sysnum); -#ifdef WINDOWS +# ifdef WINDOWS if (get_syscall_method() != SYSCALL_METHOD_SYSENTER) { DOCHECK(1, { if (get_syscall_method() == SYSCALL_METHOD_WOW64) @@ -1711,7 +1712,7 @@ bb_process_ignorable_syscall(dcontext_t *dcontext, build_bb_t *bb, int sysnum, STATS_DEC(ignorable_syscalls); return false; } -#elif defined(MACOS) && defined(X86) +# elif defined(MACOS) && defined(X86) if (instr_get_opcode(bb->instr) == OP_sysenter) { /* To continue after the sysenter we need to go to the ret ibl, as user-mode * sysenter wrappers put the retaddr into edx as the post-kernel continuation. @@ -1726,12 +1727,13 @@ bb_process_ignorable_syscall(dcontext_t *dcontext, build_bb_t *bb, int sysnum, } else if (continue_bb != NULL) *continue_bb = true; return true; -#else +# else if (continue_bb != NULL) *continue_bb = true; return true; -#endif +# endif } +#endif // LINUX_KERNEL #ifdef WINDOWS /* Process a syscall that is executed via shared syscall. */ @@ -1849,6 +1851,7 @@ adjust_it_instr_for_split(dcontext_t *dcontext, instr_t *it, uint pos) } #endif /* ARM */ +#ifndef LINUX_KERNEL static bool bb_process_non_ignorable_syscall(dcontext_t *dcontext, build_bb_t *bb, int sysnum) { @@ -1859,26 +1862,26 @@ bb_process_non_ignorable_syscall(dcontext_t *dcontext, build_bb_t *bb, int sysnu LOG(THREAD, LOG_INTERP, 3, "ending bb at syscall & removing the interrupt itself\n"); /* Indicate that this is a non-ignorable syscall so mangle will remove */ /* XXX i#1551: maybe we should union int80 and svc as both are inline syscall? */ -#ifdef UNIX +# ifdef UNIX if (instr_get_opcode(bb->instr) == IF_X86_ELSE(OP_int, IF_RISCV64_ELSE(OP_ecall, OP_svc))) { -# if defined(MACOS) && defined(X86) +# if defined(MACOS) && defined(X86) int num = instr_get_interrupt_number(bb->instr); if (num == 0x81 || num == 0x82) { bb->exit_type |= LINK_SPECIAL_EXIT; bb->instr->flags |= INSTR_BRANCH_SPECIAL_EXIT; } else { ASSERT(num == 0x80); -# endif /* MACOS && X86 */ +# endif /* MACOS && X86 */ bb->exit_type |= LINK_NI_SYSCALL_INT; bb->instr->flags |= INSTR_NI_SYSCALL_INT; -# if defined(MACOS) && defined(X86) +# if defined(MACOS) && defined(X86) } -# endif +# endif } else -#endif +# endif bb->instr->flags |= INSTR_NI_SYSCALL; -#ifdef ARM +# ifdef ARM /* we assume all conditional syscalls are treated as non-ignorable */ if (instr_is_predicated(bb->instr)) { instr_t *it; @@ -1894,13 +1897,14 @@ bb_process_non_ignorable_syscall(dcontext_t *dcontext, build_bb_t *bb, int sysnu adjust_it_instr_for_split(dcontext, it, pos); } } -#endif +# endif /* Set instr to NULL in order to get translation of exit cti correct. */ bb->instr = NULL; /* this block must be the last one in a trace */ bb->flags |= FRAG_MUST_END_TRACE; return false; /* end bb now */ } +#endif // LINUX_KERNEL /* returns true to indicate "continue bb" and false to indicate "end bb now" */ static inline bool From da3cef71df645125c396400d4a1cb12620791a2a Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 23 Jun 2026 09:23:36 -0700 Subject: [PATCH 110/156] Exclude os_dump_core_live from kernel build --- core/lib/instrument.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/lib/instrument.c b/core/lib/instrument.c index bb9e02a10..f84758cdd 100644 --- a/core/lib/instrument.c +++ b/core/lib/instrument.c @@ -2542,7 +2542,7 @@ dr_create_memory_dump(dr_memory_dump_spec_t *spec) if (TEST(DR_MEMORY_DUMP_LDMP, spec->flags)) return os_dump_core_live(spec->label, spec->ldmp_path, spec->ldmp_path_size); /* XXX i#2154: Add Android AArch64 support. */ -#elif defined(LINUX) && \ +#elif defined(LINUX) && !defined(LINUX_KERNEL) && \ ((defined(X64) && defined(X86)) || (defined(AARCH64) && !defined(ANDROID64))) if (TEST(DR_MEMORY_DUMP_ELF, spec->flags)) { return os_dump_core_live(get_thread_private_dcontext(), From 79ac0c3438a398b9ebf62c53d9b4ccc7a55b5c04 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 23 Jun 2026 09:50:55 -0700 Subject: [PATCH 111/156] Return early in dr_insert_get_seg_base for kernel build --- core/lib/instrument.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/lib/instrument.c b/core/lib/instrument.c index f84758cdd..5b2a8224b 100644 --- a/core/lib/instrument.c +++ b/core/lib/instrument.c @@ -7570,7 +7570,9 @@ dr_insert_get_seg_base(void *drcontext, instrlist_t *ilist, instr_t *instr, reg_ #ifdef X86 CLIENT_ASSERT(reg_is_segment(seg), "dr_insert_get_seg_base: seg is not a segment register"); -# ifdef UNIX +# ifdef LINUX_KERNEL + return false; +# elif defined(UNIX) # ifndef MACOS64 CLIENT_ASSERT(INTERNAL_OPTION(mangle_app_seg), "dr_insert_get_seg_base is supported with -mangle_app_seg only"); @@ -7609,7 +7611,7 @@ dr_insert_get_seg_base(void *drcontext, instrlist_t *ilist, instr_t *instr, reg_ INSTR_CREATE_mov_imm(drcontext, opnd_create_reg(reg), OPND_CREATE_INTPTR(0))); } else return false; -# endif /* UNIX/Windows */ +# endif /* LINUX_KERNEL/UNIX/Windows */ #elif defined(ARM) /* i#1551: NYI on ARM */ ASSERT_NOT_IMPLEMENTED(false); From 3736342e5bb3dd6678a1fa55ec28bb6d9b28c67d Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 23 Jun 2026 18:13:54 +0000 Subject: [PATCH 112/156] Exclude os_cxt related code in kernel build --- core/lib/instrument.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/lib/instrument.c b/core/lib/instrument.c index 5b2a8224b..faf5fd5be 100644 --- a/core/lib/instrument.c +++ b/core/lib/instrument.c @@ -6685,9 +6685,11 @@ dr_get_mcontext_priv(dcontext_t *dcontext, dr_mcontext_t *dmc, priv_mcontext_t * return true; } +#ifndef LINUX_KERNEL if (!is_os_cxt_ptr_null(dcontext->client_data->os_cxt)) { return os_context_to_mcontext(dmc, mc, dcontext->client_data->os_cxt); } +#endif if (dcontext->client_data->suspended) { /* A thread suspended by dr_suspend_all_other_threads() has its @@ -6802,6 +6804,7 @@ dr_set_mcontext(void *drcontext, dr_mcontext_t *context) if (dcontext->client_data->cur_mc != NULL) { return dr_mcontext_to_priv_mcontext(dcontext->client_data->cur_mc, context); } +#ifndef LINUX_KERNEL if (!is_os_cxt_ptr_null(dcontext->client_data->os_cxt)) { /* It would be nice to fail for #DR_XFER_CALLBACK_RETURN but we'd need to * store yet more state to do so. The pc will be ignored, and xsi @@ -6809,6 +6812,7 @@ dr_set_mcontext(void *drcontext, dr_mcontext_t *context) */ return mcontext_to_os_context(dcontext->client_data->os_cxt, context, NULL); } +#endif /* copy the machine context to the dstack area created with * dr_prepare_for_call(). note that xmm0-5 copied there From 4f4c4caf1ae3d5ddaf66cb4258777d4974fb0789 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 23 Jun 2026 18:36:56 +0000 Subject: [PATCH 113/156] Add missing definition and stubs --- core/kernel_linux/os.c | 15 +++++++++++++++ core/kernel_linux/os_exports.h | 8 ++++++++ 2 files changed, 23 insertions(+) diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index e5724a451..49acce5de 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -375,6 +375,21 @@ os_tls_offset(tls_offset_t tls_offs) return (tls_offset_t)(tls_local_state_offset + tls_offs); } +ushort +os_get_app_tls_base_offset(reg_id_t reg) +{ + ASSERT_NOT_REACHED(); + return 0; +} + +ushort +os_get_app_tls_reg_offset(reg_id_t reg) +{ + ASSERT_NOT_REACHED(); + return 0; +} + + char * get_application_pid() { diff --git a/core/kernel_linux/os_exports.h b/core/kernel_linux/os_exports.h index d463add54..3b3d599e2 100644 --- a/core/kernel_linux/os_exports.h +++ b/core/kernel_linux/os_exports.h @@ -70,6 +70,14 @@ # define ASM_SEG "%fs" #endif +#define LIB_SEG_TLS DR_REG_NULL + +ushort +os_get_app_tls_base_offset(reg_id_t reg); + +ushort +os_get_app_tls_reg_offset(reg_id_t reg); + void * get_tls(tls_offset_t tls_offs); void From b86e895ddfda9948c21186be04254ef4072afa4c Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 23 Jun 2026 18:39:51 +0000 Subject: [PATCH 114/156] Reformat --- core/kernel_linux/os.c | 1 - 1 file changed, 1 deletion(-) diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index 49acce5de..e3765dddd 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -389,7 +389,6 @@ os_get_app_tls_reg_offset(reg_id_t reg) return 0; } - char * get_application_pid() { From 3b941192b36c9130af8a01335c9d83c53c41cd59 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 23 Jun 2026 18:42:38 +0000 Subject: [PATCH 115/156] Update WHERE_FCACHE to new name DR_WHERE_FCACHE --- core/kernel_linux/os.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index e3765dddd..1912042e1 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -638,7 +638,7 @@ get_interrupted_location(dcontext_t *dcontext, interrupt_stack_frame_t *frame) ASSERT(dcontext->whereami != WHERE_USERMODE); } - if (dcontext->whereami == WHERE_FCACHE) { + if (dcontext->whereami == DR_WHERE_FCACHE) { if (in_generated_routine(dcontext, pc)) { return INTERRUPTED_GENCODE; } else if (!is_on_dstack(dcontext, (byte *)frame->xsp)) { @@ -665,9 +665,9 @@ get_interrupted_location(dcontext_t *dcontext, interrupt_stack_frame_t *frame) * * Note that the following is impossible * - in some random kernel code that we call (e.g., memcpy) after - * whereami = WHERE_FCACHE was set in the dispatcher + * whereami = DR_WHERE_FCACHE was set in the dispatcher * because we don't do anything that can fault after we set - * whereami = WHERE_FCACHE + * whereami = DR_WHERE_FCACHE */ if (is_in_dynamo_dll(pc)) { return INTERRUPTED_DYNAMORIO; @@ -692,10 +692,10 @@ get_interrupted_location(dcontext_t *dcontext, interrupt_stack_frame_t *frame) } } } else { - /* Whenever whereami != WHERE_FCACHE, we should be on the dstack. */ + /* Whenever whereami != DR_WHERE_FCACHE, we should be on the dstack. */ ASSERT(is_on_dstack(dcontext, (byte *)frame->xsp)); if (in_generated_routine(dcontext, pc)) { - /* We run some generated code when whereami != WHERE_FCACHE and not + /* We run some generated code when whereami != DR_WHERE_FCACHE and not * on the dstack (namely the kernel entry points), but these * routines should not generate exceptions and they run with * interrupts disabled. From 2b2e97849cb84858e0ed75ff7955ce53becf263b Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 23 Jun 2026 18:51:49 +0000 Subject: [PATCH 116/156] Update function signatures --- core/kernel_linux/os.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index 1912042e1..ae96f26d7 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -199,7 +199,7 @@ os_module_area_reset(module_area_t *ma HEAPACCT(which_heap_t which)) } generic_func_t -get_proc_address_ex(module_handle_t lib, const char *name, +get_proc_address_ex(module_base_t lib, const char *name, bool *is_indirect_code DR_PARAM_OUT) { ASSERT_NOT_PORTED(false); @@ -267,7 +267,7 @@ module_get_header_size(app_pc module_base) } bool -module_has_text_relocs(app_pc base) +module_has_text_relocs(app_pc base, bool at_map) { ASSERT_NOT_PORTED(false); return true; @@ -1441,7 +1441,7 @@ os_get_native_syscall_entry(dcontext_t *dcontext) } void -os_thread_init(dcontext_t *dcontext) +os_thread_init(dcontext_t *dcontext, void *os_data) { os_thread_data_t *ostd = (os_thread_data_t *)heap_alloc( dcontext, sizeof(os_thread_data_t) HEAPACCT(ACCT_OTHER)); @@ -1458,7 +1458,7 @@ os_thread_after_arch_init(dcontext_t *dcontext) } void -os_thread_exit(dcontext_t *dcontext) +os_thread_exit(dcontext_t *dcontext, bool other_thread) { os_thread_data_t *ostd = (os_thread_data_t *)dcontext->os_field; @@ -1480,7 +1480,7 @@ os_thread_under_dynamo(dcontext_t *dcontext) } void -os_thread_not_under_dynamo(dcontext_t *dcontext) +os_thread_not_under_dynamo(dcontext_t *dcontext, bool restore_sigblocked) { /* This is called when a CPU returns to user space. */ } @@ -1722,13 +1722,13 @@ get_num_processors() } shlib_handle_t -load_shared_library(char *name) +load_shared_library(const char *name, bool reachable) { return kernel_load_shared_library(name); } shlib_routine_ptr_t -lookup_library_routine(shlib_handle_t lib, char *name) +lookup_library_routine(shlib_handle_t lib, const char *name) { return kernel_lookup_library_routine(lib, name); } @@ -1750,7 +1750,8 @@ shared_library_error(char *buf, int maxlen) bool shared_library_bounds(DR_PARAM_IN shlib_handle_t lib, DR_PARAM_IN byte *addr, - DR_PARAM_OUT byte **start, DR_PARAM_OUT byte **end) + DR_PARAM_IN const char *name, DR_PARAM_OUT byte **start, + DR_PARAM_OUT byte **end) { return kernel_shared_library_bounds(lib, addr, start, end); } @@ -1947,7 +1948,7 @@ os_delete_mapped_file(const char *filename) byte * os_map_file(file_t f, size_t *size DR_PARAM_INOUT, uint64 offs, app_pc addr, uint prot, - bool copy_on_write, bool image, bool fixed) + map_flags_t map_flags) { ASSERT_NOT_PORTED(false); return NULL; @@ -2287,7 +2288,7 @@ extern void deadlock_avoidance_unlock(mutex_t *lock, bool ownable); void -mutex_wait_contended_lock(mutex_t *lock) +mutex_wait_contended_lock(mutex_t *lock, priv_mcontext_t *mc) { dcontext_t *dcontext = get_thread_private_dcontext(); /* FIXME: we don't actually use system calls to synchronize on Linux, @@ -2404,8 +2405,8 @@ reset_event(event_t e) /* FIXME: compare use and implementation with man pthread_cond_wait */ /* FIXME PR 295561: use futex */ -void -wait_for_event(event_t e) +bool +wait_for_event(event_t e, int timeout_ms) { #ifdef DEBUG dcontext_t *dcontext = get_thread_private_dcontext(); @@ -2427,7 +2428,7 @@ wait_for_event(event_t e) d_r_mutex_unlock(&e->lock); LOG(THREAD, LOG_THREADS, 3, "thread %d finished waiting for event " PFX "\n", get_thread_id(), e); - return; + return true; } } thread_yield(); From e44597ac479e749e5d6edb3037ed85e84d8dae33 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 23 Jun 2026 18:59:50 +0000 Subject: [PATCH 117/156] Add missing declaration for optimize_sys_call_ret --- core/optionsx.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/optionsx.h b/core/optionsx.h index 89bbeda03..bdb9fb519 100644 --- a/core/optionsx.h +++ b/core/optionsx.h @@ -3470,6 +3470,11 @@ OPTION_COMMAND( }, "run dr in a light weight mode with nothing but a few hooks", STATIC, OP_PCACHE_NOP) +#ifdef LINUX_KERNEL + OPTION_DEFAULT(bool, optimize_sys_call_ret, true, + "optimize syscall and sysret to avoid dispatch") +#endif + #undef OPTION #undef OPTION_NAME #undef OPTION_DEFAULT From dcad856dcb94f6cd75ff2ca34d5acc96565f5f90 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 23 Jun 2026 19:08:57 +0000 Subject: [PATCH 118/156] Copy KSTAT definitions from drk branch --- core/lib/kstatsx.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/core/lib/kstatsx.h b/core/lib/kstatsx.h index a0c035289..15e4668b1 100644 --- a/core/lib/kstatsx.h +++ b/core/lib/kstatsx.h @@ -141,6 +141,35 @@ KSTAT_DEF("in rct analysis using relocations [per page loop]", rct_reloc_per_pag KSTAT_DEF("in aslr_generate_relocated_section for validation", aslr_validate_relocate) KSTAT_DEF("in module_contents_compare or aslr_compare_in_place", aslr_compare) +#ifdef LINUX_KERNEL +KSTAT_DEF("delaying patched interrupt", delaying_patched_interrupt) +KSTAT_DEF("user interrupt handling", user_interrupt_handling) +KSTAT_DEF("kernel interrupt handling", kernel_interrupt_handling) +KSTAT_DEF("kernel interrupt fcache enter", kernel_interrupt_fcache_enter) +KSTAT_DEF("kernel interrupt fcache return", kernel_interrupt_fcache_return) +KSTAT_DEF("kernel interrupt ibl", kernel_interrupt_ibl) +KSTAT_DEF("kernel interrupt frag success page fault", kernel_interrupt_frag_success_page_fault) +KSTAT_DEF("kernel interrupt frag success other sync", kernel_interrupt_frag_success_other_sync) +KSTAT_DEF("kernel interrupt frag success async", kernel_interrupt_frag_success_async) +KSTAT_DEF("kernel interrupt frag delay dispatch", kernel_interrupt_frag_delay_dispatch) +KSTAT_DEF("kernel interrupt frag delay pc", kernel_interrupt_frag_delay_pc) +KSTAT_DEF("kernel interrupt frag unknown", kernel_interrupt_frag_unknown) +KSTAT_DEF("user mode", usermode) +KSTAT_DEF("recreate app state", recreate_app_state_failure) +KSTAT_DEF("recreate app state", recreate_app_state_success_pc) +KSTAT_DEF("recreate app state", recreate_app_state_success_state) +KSTAT_DEF("recreate app state", recreate_app_state_delay_dispatch) +KSTAT_DEF("recreate app state", recreate_app_state_delay_pc) +KSTAT_DEF("recreate app state", recreate_app_state_unknown) +KSTAT_DEF("recreate app state", recreate_app_state_frag_intr) +KSTAT_DEF("recreate app state", recreate_app_state_from_info) +KSTAT_DEF("recreate app state", recreate_app_state_in_fcache) +KSTAT_DEF("recreate app state", recreate_fragment_lookup) +KSTAT_DEF("recreate app state", recreate_fragment_ilist) +KSTAT_DEF("recreate app state", recreate_app_state_from_ilist) +KSTAT_DEF("fragment interrupt handling", fragment_interrupt_handling) +#endif /* LINUX_KERNEL */ + #ifdef KSTAT_UNIT_TEST KSTAT_DEF("empty block overhead", empty) KSTAT_DEF("total measured", measured) From 3716aa825e881250c7f7dc2804f40b1a8614a9ac Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 23 Jun 2026 19:13:29 +0000 Subject: [PATCH 119/156] Reformat --- core/optionsx.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/optionsx.h b/core/optionsx.h index bdb9fb519..b1ecdd8d9 100644 --- a/core/optionsx.h +++ b/core/optionsx.h @@ -3471,8 +3471,8 @@ OPTION_COMMAND( "run dr in a light weight mode with nothing but a few hooks", STATIC, OP_PCACHE_NOP) #ifdef LINUX_KERNEL - OPTION_DEFAULT(bool, optimize_sys_call_ret, true, - "optimize syscall and sysret to avoid dispatch") +OPTION_DEFAULT(bool, optimize_sys_call_ret, true, + "optimize syscall and sysret to avoid dispatch") #endif #undef OPTION From 6ce94e7813d06aecce5a2f287fad83d81656bee8 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 23 Jun 2026 19:17:06 +0000 Subject: [PATCH 120/156] Reformat --- core/lib/kstatsx.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/lib/kstatsx.h b/core/lib/kstatsx.h index 15e4668b1..3f62cd57b 100644 --- a/core/lib/kstatsx.h +++ b/core/lib/kstatsx.h @@ -148,8 +148,10 @@ KSTAT_DEF("kernel interrupt handling", kernel_interrupt_handling) KSTAT_DEF("kernel interrupt fcache enter", kernel_interrupt_fcache_enter) KSTAT_DEF("kernel interrupt fcache return", kernel_interrupt_fcache_return) KSTAT_DEF("kernel interrupt ibl", kernel_interrupt_ibl) -KSTAT_DEF("kernel interrupt frag success page fault", kernel_interrupt_frag_success_page_fault) -KSTAT_DEF("kernel interrupt frag success other sync", kernel_interrupt_frag_success_other_sync) +KSTAT_DEF("kernel interrupt frag success page fault", + kernel_interrupt_frag_success_page_fault) +KSTAT_DEF("kernel interrupt frag success other sync", + kernel_interrupt_frag_success_other_sync) KSTAT_DEF("kernel interrupt frag success async", kernel_interrupt_frag_success_async) KSTAT_DEF("kernel interrupt frag delay dispatch", kernel_interrupt_frag_delay_dispatch) KSTAT_DEF("kernel interrupt frag delay pc", kernel_interrupt_frag_delay_pc) From 17ba8b543023485cf9c4fc249acc916f18655417 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 23 Jun 2026 23:13:37 +0000 Subject: [PATCH 121/156] Copy next_app_tag in dcontext_t from drk branch --- core/arch/arch.c | 4 ++++ core/dynamo.c | 3 +++ core/globals.h | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/core/arch/arch.c b/core/arch/arch.c index c7215ff78..beb20e3b4 100644 --- a/core/arch/arch.c +++ b/core/arch/arch.c @@ -2818,6 +2818,10 @@ get_fcache_target(dcontext_t *dcontext) void set_fcache_target(dcontext_t *dcontext, cache_pc value) { +#ifdef LINUX_KERNEL + /* Save the last app tag. We need this to handle interrupts in fcache_enter. */ + dcontext->next_app_tag = dcontext->next_tag; +#endif /* we used to use mcontext.pc, but that's in the writable * portion of the dcontext, and so for self-protection we use the * next_tag slot, which is protected diff --git a/core/dynamo.c b/core/dynamo.c index 092b1cecf..18eab4687 100644 --- a/core/dynamo.c +++ b/core/dynamo.c @@ -1779,6 +1779,9 @@ initialize_dynamo_context(dcontext_t *dcontext) dcontext->initialized = true; dcontext->whereami = DR_WHERE_APP; dcontext->next_tag = NULL; +#ifdef LINUX_KERNEL + dcontext->next_app_tag = NULL; +#endif dcontext->native_exec_postsyscall = NULL; memset(dcontext->native_retstack, 0, sizeof(dcontext->native_retstack)); dcontext->native_retstack_cur = 0; diff --git a/core/globals.h b/core/globals.h index b88209b74..839eb0793 100644 --- a/core/globals.h +++ b/core/globals.h @@ -778,6 +778,11 @@ struct _dcontext_t { * XXX: change to a union? */ app_pc next_tag; +#ifdef LINUX_KERNEL + /* Holds the address of the next application instruction to execute. Unlike + * next_tag, this is not overwritten with a code cache address. */ + app_pc next_app_tag; +#endif linkstub_t *last_exit; /* last exit from cache */ byte *dstack; /* thread-private dynamo stack */ From 39cf637d9ccfb0f15a2227293ed91f377b493cb9 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 23 Jun 2026 23:19:17 +0000 Subject: [PATCH 122/156] Add const to function parameter type --- core/kernel_linux/kernel_interface.c | 4 ++-- core/kernel_linux/kernel_interface.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/kernel_linux/kernel_interface.c b/core/kernel_linux/kernel_interface.c index ded554af3..ea168b884 100644 --- a/core/kernel_linux/kernel_interface.c +++ b/core/kernel_linux/kernel_interface.c @@ -232,7 +232,7 @@ kernel_interface_exit(void) } void * -kernel_load_shared_library(char *name) +kernel_load_shared_library(const char *name) { struct module *module; @@ -248,7 +248,7 @@ kernel_load_shared_library(char *name) #define MAX_QUALIFIED_NAME_LEN 256 void * -kernel_lookup_library_routine(void *lib, char *name) +kernel_lookup_library_routine(void *lib, const char *name) { struct module *module = (struct module *)lib; /* Build a string with the format mod_name:routine_name. */ diff --git a/core/kernel_linux/kernel_interface.h b/core/kernel_linux/kernel_interface.h index 9a3437231..7e5648841 100644 --- a/core/kernel_linux/kernel_interface.h +++ b/core/kernel_linux/kernel_interface.h @@ -68,9 +68,9 @@ is_kernel_code(void *pc); /* None of these routines are safe to use after initilization. */ void * -kernel_load_shared_library(char *name); +kernel_load_shared_library(const char *name); void * -kernel_lookup_library_routine(void *lib, char *name); +kernel_lookup_library_routine(void *lib, const char *name); bool kernel_shared_library_bounds(void *lib, byte *addr, byte **start, byte **end); byte * From 5598331d8235366fd34ca86def524c38b2e893b2 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 23 Jun 2026 23:40:11 +0000 Subject: [PATCH 123/156] Update function signatures and usages --- core/kernel_linux/os.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index ae96f26d7..61faf7c2d 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -516,7 +516,7 @@ os_tls_cfree(uint offset, uint num_slots) /* TODO(peter): Move this to arch. */ static void -get_interrupted_context(interrupt_context_t *interrupt, dr_mcontext_t *out) +get_interrupted_context(interrupt_context_t *interrupt, priv_mcontext_t *out) { copy_mcontext(interrupt->mcontext, out); out->xip = interrupt->frame.xip; @@ -616,7 +616,7 @@ handle_user_interrupt(dcontext_t *dcontext, interrupt_context_t *interrupt) interrupt->mcontext->rsp += sizeof(interrupt->frame.error_code); } set_last_exit(dcontext, (linkstub_t *)get_user_interrupt_entry_linkstub()); - transfer_to_dispatch(dcontext, 0 /* errno */, interrupt->mcontext); + transfer_to_dispatch(dcontext, interrupt->mcontext, false); ASSERT_NOT_REACHED(); } @@ -880,7 +880,7 @@ is_loop_opc(uint opc) static void handle_fragment_interrupt(dcontext_t *dcontext, interrupt_context_t *interrupt) { - dr_mcontext_t mcontext; + priv_mcontext_t mcontext; fragment_t wrapper; recreate_success_t res; bool waslinking = is_couldbelinking(dcontext); @@ -917,7 +917,7 @@ handle_fragment_interrupt(dcontext_t *dcontext, interrupt_context_t *interrupt) dcontext->next_tag = mcontext.xip; set_last_exit(dcontext, (linkstub_t *)get_kernel_interrupt_entry_linkstub()); STATS_INC(num_ndelayed_frag_intr); - transfer_to_dispatch(dcontext, 0, &mcontext); + transfer_to_dispatch(dcontext, &mcontext, false); } else if (res == RECREATE_DELAY_UNTIL_DISPATCH) { /* Switch from kernel_interrupt_handling */ KSWITCH(kernel_interrupt_frag_delay_dispatch); @@ -1000,7 +1000,7 @@ handle_fcache_enter_interrupt(dcontext_t *dcontext, interrupt_context_t *interru ASSERT(!is_dynamo_address(dcontext->next_tag)); ASSERT(is_kernel_code(dcontext->next_tag)); STATS_INC(num_fcache_enter_interrupts); - transfer_to_dispatch(dcontext, 0, get_mcontext(dcontext)); + transfer_to_dispatch(dcontext, get_mcontext(dcontext), false); } static void From 4deb956d65fdf4c248886ab1d3bc4917a160a0ce Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 23 Jun 2026 23:44:07 +0000 Subject: [PATCH 124/156] dr_mcontext_t -> priv_mcontext_t --- core/kernel_linux/os.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index 61faf7c2d..843aed69f 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -98,7 +98,7 @@ typedef struct { interrupt_stack_frame_t frame; /* Keep a pointer around so we can reset eflags.IF. */ interrupt_stack_frame_t *raw_frame; - dr_mcontext_t *mcontext; + priv_mcontext_t *mcontext; interrupt_vector_t vector; interrupted_location_t location; } interrupt_context_t; @@ -117,7 +117,7 @@ typedef struct { /* State of the pending interrupt. */ bool pending_interrupt; bool use_interrupted_mcontext; - dr_mcontext_t interrupted_mcontext; + priv_mcontext_t interrupted_mcontext; interrupt_vector_t interrupt_vector; reg_t interrupt_error_code; reg_t interrupt_system_xflags; @@ -538,7 +538,7 @@ redirect_iret_to_fcache_return(dcontext_t *dcontext, /* TODO(peter): Move this to arch. */ static void -emulate_interrupt_arrival(dr_mcontext_t *mcontext, interrupt_vector_t vector, +emulate_interrupt_arrival(priv_mcontext_t *mcontext, interrupt_vector_t vector, byte *handler, reg_t error_code, reg_t system_xflags, bool frame_if) { @@ -846,7 +846,7 @@ receive_pending_interrupt(dcontext_t *dcontext) static void record_pending_interrupt(dcontext_t *dcontext, interrupt_context_t *interrupt, - dr_mcontext_t *interrupted_mcontext, bool modify_if) + priv_mcontext_t *interrupted_mcontext, bool modify_if) { os_thread_data_t *ostd = (os_thread_data_t *)dcontext->os_field; ostd->pending_interrupt = true; @@ -1099,7 +1099,7 @@ send_interrupt_to_client(dcontext_t *dcontext, interrupt_context_t *interrupt) } static void -handle_interrupt(interrupt_stack_frame_t *frame, dr_mcontext_t *mcontext, +handle_interrupt(interrupt_stack_frame_t *frame, priv_mcontext_t *mcontext, interrupt_vector_t vector) { dcontext_t *dcontext; From a7a57ecd2eb9ba347b1a68296895c3a86bd2c1b9 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 24 Jun 2026 20:26:44 +0000 Subject: [PATCH 125/156] Port in definitions of EFLAGS_IF and EFLAGS_SYSTEM --- core/ir/instr_api.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/ir/instr_api.h b/core/ir/instr_api.h index 5956bfaaa..000ebd0ce 100644 --- a/core/ir/instr_api.h +++ b/core/ir/instr_api.h @@ -2585,10 +2585,13 @@ enum { EFLAGS_AF = 0x00000010, /**< The bit in the eflags register of AF (Aux Carry Flag). */ EFLAGS_ZF = 0x00000040, /**< The bit in the eflags register of ZF (Zero Flag). */ EFLAGS_SF = 0x00000080, /**< The bit in the eflags register of SF (Sign Flag). */ + EFLAGS_IF = 0x00000200, /**< The bit in the eflags register of IF (Interrupt Enable Flag). */ EFLAGS_DF = 0x00000400, /**< The bit in the eflags register of DF (Direction Flag). */ EFLAGS_OF = 0x00000800, /**< The bit in the eflags register of OF (Overflow Flag). */ /** The bits in the eflags register of CF, PF, AF, ZF, SF, OF. */ EFLAGS_ARITH = EFLAGS_CF | EFLAGS_PF | EFLAGS_AF | EFLAGS_ZF | EFLAGS_SF | EFLAGS_OF, + EFLAGS_NON_SYSTEM = EFLAGS_ARITH | EFLAGS_DF, + EFLAGS_SYSTEM = ~EFLAGS_NON_SYSTEM, }; #elif defined(AARCHXX) From ab73cd4335c14b583a5d0494b5cc8985c81cc41c Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 24 Jun 2026 20:27:26 +0000 Subject: [PATCH 126/156] Correct usage of recreate_app_state() --- core/kernel_linux/os.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index 843aed69f..fe06a5a48 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -897,7 +897,7 @@ handle_fragment_interrupt(dcontext_t *dcontext, interrupt_context_t *interrupt) KSTART(recreate_app_state_frag_intr); if (!waslinking) enter_couldbelinking(dcontext, NULL, false); - res = recreate_app_state(dcontext, &mcontext, true); + res = recreate_app_state(dcontext, &mcontext, true, NULL); if (!waslinking) enter_nolinking(dcontext, NULL, false); KSTOP(recreate_app_state_frag_intr); From 52ff37c85525a0a42553098aae67511e11413c3e Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 24 Jun 2026 20:31:46 +0000 Subject: [PATCH 127/156] Reformat --- core/ir/instr_api.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/ir/instr_api.h b/core/ir/instr_api.h index 000ebd0ce..9f8548f62 100644 --- a/core/ir/instr_api.h +++ b/core/ir/instr_api.h @@ -2585,7 +2585,8 @@ enum { EFLAGS_AF = 0x00000010, /**< The bit in the eflags register of AF (Aux Carry Flag). */ EFLAGS_ZF = 0x00000040, /**< The bit in the eflags register of ZF (Zero Flag). */ EFLAGS_SF = 0x00000080, /**< The bit in the eflags register of SF (Sign Flag). */ - EFLAGS_IF = 0x00000200, /**< The bit in the eflags register of IF (Interrupt Enable Flag). */ + EFLAGS_IF = + 0x00000200, /**< The bit in the eflags register of IF (Interrupt Enable Flag). */ EFLAGS_DF = 0x00000400, /**< The bit in the eflags register of DF (Direction Flag). */ EFLAGS_OF = 0x00000800, /**< The bit in the eflags register of OF (Overflow Flag). */ /** The bits in the eflags register of CF, PF, AF, ZF, SF, OF. */ From 91c1c4cad871df23f461651f8762f6c75783f3b9 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 24 Jun 2026 21:54:08 +0000 Subject: [PATCH 128/156] Port in variants of enum recreate_success_t from drk branch RECREATE_DELAY_UNTIL_DISPATCH and RECREATE_DELAY_UNTIL_PC were added in the drk implementation. --- core/translate.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/translate.h b/core/translate.h index 7c88623f8..a62ec8d46 100644 --- a/core/translate.h +++ b/core/translate.h @@ -93,6 +93,8 @@ typedef enum { RECREATE_FAILURE, RECREATE_SUCCESS_PC, RECREATE_SUCCESS_STATE, + RECREATE_DELAY_UNTIL_DISPATCH, + RECREATE_DELAY_UNTIL_PC, } recreate_success_t; recreate_success_t From 897c907e18e88498757289428fa009e4ae49a273 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 24 Jun 2026 23:06:14 +0000 Subject: [PATCH 129/156] Implement os_random_seed() in core/kernel_linux/os.c --- core/kernel_linux/os.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index fe06a5a48..918b8705b 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -2438,10 +2438,12 @@ wait_for_event(event_t e, int timeout_ms) /* End of code copied from the original Linux port. */ uint -os_random_seed() +os_random_seed(void) { /* Return the low 32 bits of the cycle count. */ - return (uint)get_cycle_count(); + uint64 cycles = 0; + RDTSC_LL(cycles); + return (uint)cycles; } void From 4f1f367faa18ef1d4d3158df25bd566dfa66beb1 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 24 Jun 2026 23:18:03 +0000 Subject: [PATCH 130/156] Port in optimize_syscall_code from drk branch --- core/arch/arch.c | 13 +++++++++++++ core/arch/arch_exports.h | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/core/arch/arch.c b/core/arch/arch.c index beb20e3b4..96ffd8815 100644 --- a/core/arch/arch.c +++ b/core/arch/arch.c @@ -1180,6 +1180,19 @@ emit_syscall_routines(dcontext_t *dcontext, generated_code_t *code, byte *pc, return pc; } +#ifdef LINUX_KERNEL +void +optimize_syscall_code(dcontext_t *dcontext, fragment_t *f) +{ + generated_code_t *code = THREAD_GENCODE(dcontext); + byte *pc = code->syscall_entry; + /* Assert pc points to swapgs. */ + ASSERT(pc[0] == 0x0f && pc[1] == 0x01 && pc[2] == 0xf8); + pc += 3; + insert_relative_jump(pc, f->start_pc, false); +} +#endif + void arch_thread_init(dcontext_t *dcontext) { diff --git a/core/arch/arch_exports.h b/core/arch/arch_exports.h index f2f46b251..cf15dd75a 100644 --- a/core/arch/arch_exports.h +++ b/core/arch/arch_exports.h @@ -422,6 +422,10 @@ get_time(void); void d_r_arch_init(void); void d_r_arch_exit(IF_WINDOWS_ELSE_NP(bool detach_stacked_callbacks, void)); +#ifdef LINUX_KERNEL +void +optimize_syscall_code(dcontext_t *dcontext, fragment_t *f); +#endif void arch_thread_init(dcontext_t *dcontext); void From 7b58f5f50f7af837a74a5d891bba046f898f2572 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Wed, 24 Jun 2026 23:47:59 +0000 Subject: [PATCH 131/156] Fix in_fcache_enter/in_fcache_return --- core/arch/arch.c | 28 ++++++++++++++++++++++++++++ core/arch/arch.h | 1 + core/arch/arch_exports.h | 2 ++ core/kernel_linux/os.c | 4 ++-- 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/core/arch/arch.c b/core/arch/arch.c index 96ffd8815..b887f1cd5 100644 --- a/core/arch/arch.c +++ b/core/arch/arch.c @@ -327,6 +327,7 @@ shared_gencode_emit(generated_code_t *gencode _IF_X86_64(bool x86_mode)) pc = check_size_and_cache_line(isa_mode, gencode, pc); gencode->fcache_enter = pc; pc = emit_fcache_enter_shared(GLOBAL_DCONTEXT, gencode, pc); + gencode->fcache_enter_end = pc; pc = check_size_and_cache_line(isa_mode, gencode, pc); gencode->fcache_return = pc; pc = emit_fcache_return_shared(GLOBAL_DCONTEXT, gencode, pc); @@ -1298,6 +1299,7 @@ arch_thread_init(dcontext_t *dcontext) pc = check_size_and_cache_line(isa_mode, code, pc); code->fcache_enter = pc; pc = emit_fcache_enter(dcontext, code, pc); + code->fcache_enter_end = pc; pc = check_size_and_cache_line(isa_mode, code, pc); code->fcache_return = pc; pc = emit_fcache_return(dcontext, code, pc); @@ -1796,6 +1798,32 @@ in_generated_routine(dcontext_t *dcontext, cache_pc pc) /* XXX: what about inlined IBL stubs */ } +static bool +in_fcache_enter_for_gencode(generated_code_t *code, cache_pc pc) +{ + return pc != NULL && pc >= code->fcache_enter && pc < code->fcache_enter_end; +} + +bool +in_fcache_enter(dcontext_t *dcontext, cache_pc pc) +{ + generated_code_t *code = THREAD_GENCODE(dcontext); + if (in_fcache_enter_for_gencode(code, pc)) + return true; + if (USE_SHARED_GENCODE()) { + if (in_fcache_enter_for_gencode(shared_code, pc)) + return true; +#if defined(X86) && defined(X64) + if (shared_code_x86 != NULL && in_fcache_enter_for_gencode(shared_code_x86, pc)) + return true; + if (shared_code_x86_to_x64 != NULL && + in_fcache_enter_for_gencode(shared_code_x86_to_x64, pc)) + return true; +#endif + } + return false; +} + static bool in_fcache_return_for_gencode(generated_code_t *code, cache_pc pc) { diff --git a/core/arch/arch.h b/core/arch/arch.h index f92aeb696..b3c69872f 100644 --- a/core/arch/arch.h +++ b/core/arch/arch.h @@ -957,6 +957,7 @@ typedef struct ibl_code_t { */ typedef struct _generated_code_t { byte *fcache_enter; + byte *fcache_enter_end; byte *fcache_return; byte *fcache_return_end; #ifdef WINDOWS_PC_SAMPLE diff --git a/core/arch/arch_exports.h b/core/arch/arch_exports.h index cf15dd75a..49a23553c 100644 --- a/core/arch/arch_exports.h +++ b/core/arch/arch_exports.h @@ -449,6 +449,8 @@ is_indirect_branch_lookup_routine(dcontext_t *dcontext, cache_pc pc); bool in_generated_routine(dcontext_t *dcontext, cache_pc pc); bool +in_fcache_enter(dcontext_t *dcontext, cache_pc pc); +bool in_fcache_return(dcontext_t *dcontext, cache_pc pc); bool in_clean_call_save(dcontext_t *dcontext, cache_pc pc); diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index 918b8705b..e3924d2fd 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -1046,9 +1046,9 @@ handle_kernel_interrupt(dcontext_t *dcontext, interrupt_context_t *interrupt) ASSERT(!vector_is_synchronous(interrupt->vector)); if (in_indirect_branch_lookup_code(dcontext, interrupt->frame.xip)) { handle_ibl_interrupt(dcontext, interrupt); - } else if (in_fcache_enter_code(dcontext, interrupt->frame.xip)) { + } else if (in_fcache_enter(dcontext, interrupt->frame.xip)) { handle_fcache_enter_interrupt(dcontext, interrupt); - } else if (in_fcache_return_code(dcontext, interrupt->frame.xip)) { + } else if (in_fcache_return(dcontext, interrupt->frame.xip)) { handle_fcache_return_interrupt(dcontext, interrupt); } else { /* We don't expect interrupts for any other gencode. */ From b16934642349623d855cab4dbe0e4e9bd5bf4ee5 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Fri, 26 Jun 2026 17:55:26 +0000 Subject: [PATCH 132/156] Port syscall and interrupt entry handlers from drk --- core/arch/arch.c | 59 ++++++ core/arch/arch.h | 16 ++ core/arch/arch_exports.h | 22 ++- core/arch/x86/emit_utils.c | 368 +++++++++++++++++++++++++++++++++++++ 4 files changed, 464 insertions(+), 1 deletion(-) diff --git a/core/arch/arch.c b/core/arch/arch.c index b887f1cd5..fe5acb7d2 100644 --- a/core/arch/arch.c +++ b/core/arch/arch.c @@ -1149,6 +1149,25 @@ emit_syscall_routines(dcontext_t *dcontext, generated_code_t *code, byte *pc, code->do_syscall = pc; pc = emit_do_syscall(dcontext, code, pc, code->fcache_return, thread_shared, 0, &code->do_syscall_offs); +#elif defined(LINUX_KERNEL) + ASSERT(thread_shared); + pc = check_size_and_cache_line(isa_mode, code, pc); + code->syscall_entry = pc; + pc = emit_syscall_entry(dcontext, code->fcache_return, + os_get_native_syscall_entry(dcontext), pc); + pc = check_size_and_cache_line(isa_mode, code, pc); + code->common_vector_entry = pc; + pc = emit_common_vector_entry(dcontext, os_get_tls_base(dcontext), + os_get_interrupt_handler(0), pc); + pc = check_size_and_cache_line(isa_mode, code, pc); + for (int vector = VECTOR_START; vector < VECTOR_END; vector++) { + /* Pack as many as we can on a cache line. */ + if (CROSSES_ALIGNMENT(pc, VECTOR_ENTRY_CODE_SIZE, proc_get_cache_line_size())) { + pc = check_size_and_cache_line(isa_mode, code, pc); + } + code->vector_entry[vector - VECTOR_START] = pc; + pc = emit_vector_entry(dcontext, code->common_vector_entry, vector, pc); + } #else /* UNIX */ pc = check_size_and_cache_line(isa_mode, code, pc); code->do_syscall = pc; @@ -2019,6 +2038,46 @@ get_do_vmkuw_syscall_entry(dcontext_t *dcontext) # endif #endif +#ifdef LINUX_KERNEL +cache_pc +get_syscall_entry(dcontext_t *dcontext) { + generated_code_t *code = THREAD_GENCODE(dcontext); + return (cache_pc)code->syscall_entry; +} + +cache_pc +get_vector_entry(dcontext_t *dcontext, interrupt_vector_t vector) { + generated_code_t *code = THREAD_GENCODE(dcontext); + ASSERT(vector >= VECTOR_START && vector < VECTOR_END); + return (cache_pc)code->vector_entry[vector - VECTOR_START]; +} + +bool +vector_has_error_code(interrupt_vector_t vector) +{ + ASSERT(vector >= VECTOR_START && vector < VECTOR_END); + switch (vector) { + case VECTOR_DOUBLE_FAULT: + case VECTOR_INVALID_TSS: + case VECTOR_SEGMENT_NOT_PRESENT: + case VECTOR_STACK_FAULT: + case VECTOR_GENERAL_PROTECTION: + case VECTOR_PAGE_FAULT: + case VECTOR_ALIGNMENT_CHECK: + return true; + default: + return false; + } +} + +bool +vector_is_synchronous(interrupt_vector_t vector) +{ + ASSERT(vector >= VECTOR_START && vector < VECTOR_END); + return vector >= VECTOR_EXCEPTION_START && vector < VECTOR_EXCEPTION_END; +} +#endif + cache_pc fcache_return_routine(dcontext_t *dcontext) { diff --git a/core/arch/arch.h b/core/arch/arch.h index b3c69872f..571e5f9bd 100644 --- a/core/arch/arch.h +++ b/core/arch/arch.h @@ -1048,6 +1048,12 @@ typedef struct _generated_code_t { byte *clean_call_restore; byte *clean_call_restore_end; +#ifdef LINUX_KERNEL + byte *syscall_entry; + byte *common_vector_entry; + byte *vector_entry[VECTOR_END - VECTOR_START]; +#endif + bool thread_shared; bool writable; #if defined(X86) && defined(X64) @@ -1266,6 +1272,16 @@ emit_do_syscall(dcontext_t *dcontext, generated_code_t *code, byte *pc, byte *fcache_return_pc, bool thread_shared, int interrupt, uint *syscall_offs /*OUT*/); +#ifdef LINUX_KERNEL +# define VECTOR_ENTRY_CODE_SIZE (2 * PUSH_IMM32_LENGTH + JMP_LONG_LENGTH) +byte * +emit_syscall_entry(dcontext_t *dcontext, cache_pc fcache_return, app_pc target, cache_pc pc); +byte * +emit_common_vector_entry(dcontext_t *dcontext, byte *tls_base, interrupt_handler_t handler, cache_pc pc); +byte * +emit_vector_entry(dcontext_t *dcontext, byte *common_vector_entry_pc, interrupt_vector_t vector, cache_pc pc); +#endif + #ifdef AARCH64 /* Generate move (immediate) of a 64-bit value using at most 4 instructions. * pc must be a writable (vmcode) pc. diff --git a/core/arch/arch_exports.h b/core/arch/arch_exports.h index 49a23553c..0ab6d2292 100644 --- a/core/arch/arch_exports.h +++ b/core/arch/arch_exports.h @@ -1928,10 +1928,30 @@ typedef struct { reg_t ss; } interrupt_stack_frame_t; +/* Returns true if the hardware normally pushes an error code on this vector's + * interrupt stack frame. + */ +bool +vector_has_error_code(interrupt_vector_t vector); + +/* Returns true if the interrupt vector corresponds to a synchronous CPU exception. */ +bool +vector_is_synchronous(interrupt_vector_t vector); + # define INTERRUPT_STACK_FRAME_ALIGNMENT 0x10 -typedef void (*interrupt_handler_t)(interrupt_stack_frame_t *, dr_mcontext_t *, +typedef void (*interrupt_handler_t)(interrupt_stack_frame_t *, priv_mcontext_t *, interrupt_vector_t); + +/* Returns the gencode for syscall entry. */ +cache_pc +get_syscall_entry(dcontext_t *dcontext); +/* Returns the gencode for vector entry. */ +cache_pc +get_vector_entry(dcontext_t *dcontext, interrupt_vector_t vector); + +bool +vector_is_synchronous(interrupt_vector_t vector); #endif /* LINUX_KERNEL */ #endif /* _ARCH_EXPORTS_H_ */ diff --git a/core/arch/x86/emit_utils.c b/core/arch/x86/emit_utils.c index 3fc21b15c..da72b61c7 100644 --- a/core/arch/x86/emit_utils.c +++ b/core/arch/x86/emit_utils.c @@ -3143,6 +3143,374 @@ fill_with_nops(dr_isa_mode_t isa_mode, byte *addr, size_t size) return true; } +#ifdef LINUX_KERNEL +/* + # It's important to not use the native stack in this routine. x86 does not + # automatically switch stacks on system calls. So, if we pushed things here, + # then we would overwrite anything on the user's stack past %rsp. + swapgs + mov %xdi, %gs:DCONTEXT_BASE_SPILL_SLOT + mov %gs:TLS_DCONTEXT_SLOT, %xdi + mov %xax, %gs:TLS_XAX_SLOT + # dcontext->next_tag = target + mov target, %xax + mov %xax, NEXT_TAG_OFFSET(%xdi) + # xax = get_syscall_entry_linkstub(). fcache_return sets + # dcontext->last_exit = xax. + mov get_syscall_entry_linkstub(), %xax + # restore %xdi + mov %gs:DCONTEXT_BASE_SPILL_SLOT, %xdi + jmp fcache_return + jmp unexpected_return + */ +byte * +emit_syscall_entry(dcontext_t *dcontext, cache_pc fcache_return, app_pc target, cache_pc pc) { + instr_t *swapgs = instr_create(dcontext); + + /* TODO i#31: If Kernel Indirect Branch Tracking (IBT) is enabled, the first instruction + * at target (entry_SYSCALL_64) is endbr64 (0xf3 0x0f 0x1e 0xfa). Skip it + * since endbr64 is not yet implemented in DynamoRIO's opcode tables. + */ + if (target[0] == 0xf3 && target[1] == 0x0f && target[2] == 0x1e && target[3] == 0xfa) { + target += 4; + } + + decode(dcontext, target, swapgs); + ASSERT(instr_get_opcode(swapgs) == OP_swapgs); + + instrlist_t *ilist = instrlist_create(dcontext); + APP(ilist, swapgs); + /* Save XAX and XDI. Get dcontext into XDI. */ + append_shared_get_dcontext(dcontext, ilist, true /* save_xdi */); + APP(ilist, SAVE_TO_TLS(dcontext, REG_XAX, TLS_XAX_SLOT)); + /* dcontext->next_tag = target */ + APP(ilist, + INSTR_CREATE_mov_imm(dcontext, opnd_create_reg(REG_XAX), + OPND_CREATE_INTPTR(target))); + APP(ilist, SAVE_TO_DC_VIA_REG(false, dcontext, REG_XDI, REG_XAX, NEXT_TAG_OFFSET)); + /* XAX = get_syscall_entry_linkstub() (fcache_return sets + * dcontext->last_exit = XAX) */ + APP(ilist, + INSTR_CREATE_mov_imm(dcontext, opnd_create_reg(REG_XAX), + OPND_CREATE_INTPTR(get_syscall_entry_linkstub()))); + /* Restore XDI. Don't need to restore XAX because fcache_return does that + * for us. */ + append_shared_restore_dcontext_reg(dcontext, ilist); + /* Do fcache_return. */ + APP(ilist, INSTR_CREATE_jmp(dcontext, opnd_create_pc(fcache_return))); + APP(ilist, INSTR_CREATE_jmp(dcontext, opnd_create_pc((app_pc)unexpected_return))); + pc = instrlist_encode(dcontext, ilist, pc, false); + instrlist_clear_and_destroy(dcontext, ilist); + return pc; +} + +/* Pushes mcontext onto the stack with pc = 0 and xmm registers with garbage + values. Clobbers xax. + + # Push an mcontext onto the stack. For now, we push 0 in place of %pc to + # indicate an invalid pc. The dispatcher will have to load the native + # entry point from the OS module. + push 0 + pushf + lea [%rsp - XMM_SLOTS_SIZE], %rsp + push %r15 + ... + push %r8 + push %xax + push %xcx + push %xdx + push %xbx + push %xsp + push %xbp + push %xsi + push %xdi + # Save the correct %xsp by offsetting the pushed mcontext and anything + # else that was pushed on the stack (i.e., extra_stack bytes). + # mcontext.xsp = %xsp + sizeof(dr_mcontext_t) + extra_stack + lea [%xsp + sizeof(dr_mcontext_t) + sizeof(reg_t)], %xax + mov %xax, [%xsp + offsetof(dr_mcontext_t, xsp)] +*/ + +static void +append_push_mcontext(dcontext_t *dcontext, int extra_stack, instrlist_t *ilist) +{ + int simd_slots_size = + MCXT_TOTAL_SIMD_SLOTS_SIZE + MCXT_TOTAL_OPMASK_SLOTS_SIZE + PRE_XMM_PADDING; + /* push %pc - use 0 to indicate that it's invalid */ + APP(ilist, INSTR_CREATE_push_imm(dcontext, OPND_CREATE_INT32(0))); + APP(ilist, INSTR_CREATE_RAW_pushf(dcontext)); + ASSERT(!preserve_xmm_caller_saved()); + APP(ilist, INSTR_CREATE_lea( + dcontext, opnd_create_reg(REG_XSP), + opnd_create_base_disp(REG_XSP, REG_NULL, 0, -simd_slots_size, OPSZ_lea))); +#ifdef X64 + APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_R15))); + APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_R14))); + APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_R13))); + APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_R12))); + APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_R11))); + APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_R10))); + APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_R9))); + APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_R8))); +#endif + APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_XAX))); + APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_XCX))); + APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_XDX))); + APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_XBX))); + APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_XSP))); + APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_XBP))); + APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_XSI))); + APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_XDI))); + /* We pushed the wrong value for rsp. Fix that. */ + APP(ilist, INSTR_CREATE_lea( + dcontext, opnd_create_reg(REG_XAX), + opnd_create_base_disp(REG_XSP, REG_NULL, 0, + sizeof(priv_mcontext_t) + extra_stack, OPSZ_lea))); + APP(ilist, INSTR_CREATE_mov_st( + dcontext, + opnd_create_base_disp(REG_XSP, REG_NULL, 0, + offsetof(priv_mcontext_t, xsp), OPSZ_PTR), + opnd_create_reg(REG_XAX))); +} + +/* + Expects an interrupt stack frame with the vector number and error pushed + onto it. The stack is created like this where rsp = mcontext->rsp = native + rsp at the beginning of the interrupt handler. + + ss + xsp + xflags + cs + xip + error_code rsp + vector rsp - 8 + mcontext->pc rsp - 16 + ... the rest of mcontext + + + + # Restore the Kernel's GS base if necessary. + mov $MSR_GS_BASE, %rcx + rdmsr + shl $32, %rdx + or %rax, %rdx + mov $tls_base, %rcx + cmp %rcx, %rdx + jeq no_swapgs: + swapgs + no_swapgs: + + # Save handler arguments into registers. + lea [%rsp + sizeof(dr_mcontext_t)], %rax + mov %rsp, %rbx + mov [%rsp + sizeof(dr_mcontext_t) + sizeof(reg_t)], %rcx + + old_rsp = rsp + if (!on_dstack(rsp)) { + swap_stacks() + } + push(old_rsp) + handle_interrupt() + pop(rsp), so rsp = old_rsp + + # Swap stacks if we aren't already on the dstack. + mov %rsp, %r8 + # if rsp > dcontext->dstack, then goto swap_stacks + mov dcontext->dstack, %rdx + cmp %rdx, %rsp + jg swap_stacks + # if rsp < (smallest addr in dstack), + # then goto swapped_stacks + mov dcontext->dstack - DYNAMORIO_STACK_SIZE, %rdx + cmp %rdx, %rsp + jg swapped_stacks + swap_stacks: + mov dcontext->dstack, %rsp + swapped_stacks: + push %r8 + + # Call the handler. + handler(isf=%rax, mcontext=%rbx, vector=%rcx) + + # Restore native stack pointer. + pop %rsp + + # pop off mcontext + pop %xdi + pop %xsi + pop %xbp + pop %xsp + pop %xbx + pop %xdx + pop %xcx + pop %xax + pop %r8 + ... + pop %r15 + # Pop off unused XMM registers and dead xflags, xip, vector, and the + # error code. + lea [%rsp + simd_slots_size + sizeof(reg_t) * 4], %rsp + + iret +*/ +byte * +emit_common_vector_entry(dcontext_t *dcontext, byte *tls_base, + interrupt_handler_t handler, cache_pc pc) +{ + instrlist_t *ilist = instrlist_create(dcontext); + instr_t *no_swapgs = INSTR_CREATE_label(dcontext); + instr_t *swap_stacks = INSTR_CREATE_label(dcontext); + instr_t *swapped_stacks = INSTR_CREATE_label(dcontext); + int simd_slots_size = + MCXT_TOTAL_SIMD_SLOTS_SIZE + MCXT_TOTAL_OPMASK_SLOTS_SIZE + PRE_XMM_PADDING; + /* After we push mcontext, the stack contains + * mcontext + * vector + * interrupt stack frame (isf) + * if the isf does not have an error code, then we point the first byte of + * isf (i.e., the error code) to vector. + */ + int vector_offset = sizeof(priv_mcontext_t); + int isf_offset = vector_offset + sizeof(reg_t); + + append_push_mcontext(dcontext, sizeof(reg_t), ilist); + + /* Check if TLS is setup. Perform a swapgs if necessary. + * TODO(peter): We'll make this much more efficient when we implement FS + * stealing. In particular, we'll know which instruction addresses can fault + * with the native FS value. Knowing that, we won't have to check the MSR. + */ + APP(ilist, + INSTR_CREATE_mov_imm(dcontext, opnd_create_reg(REG_XCX), + OPND_CREATE_INT64(MSR_GS_BASE))); + APP(ilist, INSTR_CREATE_rdmsr(dcontext)); + APP(ilist, + INSTR_CREATE_shl(dcontext, opnd_create_reg(REG_XDX), OPND_CREATE_INT8(32))); + APP(ilist, + INSTR_CREATE_or(dcontext, opnd_create_reg(REG_XDX), opnd_create_reg(REG_XAX))); + APP(ilist, + INSTR_CREATE_mov_imm(dcontext, opnd_create_reg(REG_XCX), + OPND_CREATE_INT64(tls_base))); + APP(ilist, + INSTR_CREATE_cmp(dcontext, opnd_create_reg(REG_XCX), opnd_create_reg(REG_XDX))); + APP(ilist, INSTR_CREATE_jcc(dcontext, OP_je, opnd_create_instr(no_swapgs))); + APP(ilist, INSTR_CREATE_swapgs(dcontext)); + APP(ilist, no_swapgs); + + /* Set rax = isf, rbx = mcontext, and rcx = vector then call + * handler(isf, mcontext, vector). + */ + APP(ilist, + INSTR_CREATE_lea( + dcontext, opnd_create_reg(REG_RAX), + opnd_create_base_disp(REG_XSP, REG_NULL, 0, isf_offset, OPSZ_lea))); + APP(ilist, + INSTR_CREATE_mov_ld(dcontext, opnd_create_reg(REG_RBX), + opnd_create_reg(REG_XSP))); + APP(ilist, + INSTR_CREATE_mov_ld( + dcontext, opnd_create_reg(REG_RCX), + opnd_create_base_disp(REG_XSP, REG_NULL, 0, vector_offset, OPSZ_PTR))); + + /* Use r8 to backup rsp for after the handler. */ + APP(ilist, + INSTR_CREATE_mov_st(dcontext, opnd_create_reg(REG_R8), opnd_create_reg(REG_RSP))); + /* rdx = dcontext->dstack */ + /* TODO(peter): We could probably perform this check with an immediate in + * cmp as long as the dstack address can be represented with a 32-bit sign + * extended value. */ + APP(ilist, + INSTR_CREATE_mov_imm( + dcontext, opnd_create_reg(REG_RDX), + opnd_create_immed_int((ptr_int_t)dcontext->dstack, OPSZ_PTR))); + /* TODO(peter): Kernel stacks are normally at lower addresses than the start + * of the dstack (i.e., this branch normally falls through). We could + * optimize this code by having the common check first + * (if rsp <= dstack - DYNAMORIO_STACK_SIZE). + */ + APP(ilist, + INSTR_CREATE_cmp(dcontext, opnd_create_reg(REG_RSP), opnd_create_reg(REG_RDX))); + APP(ilist, INSTR_CREATE_jcc(dcontext, OP_jg, opnd_create_instr(swap_stacks))); + APP(ilist, + INSTR_CREATE_mov_imm( + dcontext, opnd_create_reg(REG_RDX), + opnd_create_immed_int((ptr_int_t)(dcontext->dstack - DYNAMORIO_STACK_SIZE), + OPSZ_PTR))); + APP(ilist, + INSTR_CREATE_cmp(dcontext, opnd_create_reg(REG_RSP), opnd_create_reg(REG_RDX))); + APP(ilist, INSTR_CREATE_jcc(dcontext, OP_jg, opnd_create_instr(swapped_stacks))); + APP(ilist, swap_stacks); + APP(ilist, + INSTR_CREATE_mov_imm( + dcontext, opnd_create_reg(REG_RSP), + opnd_create_immed_int((ptr_int_t)dcontext->dstack, OPSZ_PTR))); + APP(ilist, swapped_stacks); + /* Push the old stack pointer value. */ + APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_R8))); + + dr_insert_call(dcontext, ilist, NULL /*append*/, handler, 3, opnd_create_reg(REG_RAX), + opnd_create_reg(REG_RBX), opnd_create_reg(REG_RCX)); + + /* Restore the old stack pointer. Note that we could use callee-saved R12 + * instead of R8 and avoid the push/pop. I'm using push/pop just in case ;-) + */ + APP(ilist, INSTR_CREATE_pop(dcontext, opnd_create_reg(REG_RSP))); + + /* Restore the registers stored in mcontext. */ + APP(ilist, INSTR_CREATE_pop(dcontext, opnd_create_reg(REG_RDI))); + APP(ilist, INSTR_CREATE_pop(dcontext, opnd_create_reg(REG_RSI))); + APP(ilist, INSTR_CREATE_pop(dcontext, opnd_create_reg(REG_RBP))); + /* pop RSP into dead RBX */ + APP(ilist, INSTR_CREATE_pop(dcontext, opnd_create_reg(REG_RBX))); + APP(ilist, INSTR_CREATE_pop(dcontext, opnd_create_reg(REG_RBX))); + APP(ilist, INSTR_CREATE_pop(dcontext, opnd_create_reg(REG_RDX))); + APP(ilist, INSTR_CREATE_pop(dcontext, opnd_create_reg(REG_RCX))); + APP(ilist, INSTR_CREATE_pop(dcontext, opnd_create_reg(REG_RAX))); + APP(ilist, INSTR_CREATE_pop(dcontext, opnd_create_reg(REG_R8))); + APP(ilist, INSTR_CREATE_pop(dcontext, opnd_create_reg(REG_R9))); + APP(ilist, INSTR_CREATE_pop(dcontext, opnd_create_reg(REG_R10))); + APP(ilist, INSTR_CREATE_pop(dcontext, opnd_create_reg(REG_R11))); + APP(ilist, INSTR_CREATE_pop(dcontext, opnd_create_reg(REG_R12))); + APP(ilist, INSTR_CREATE_pop(dcontext, opnd_create_reg(REG_R13))); + APP(ilist, INSTR_CREATE_pop(dcontext, opnd_create_reg(REG_R14))); + APP(ilist, INSTR_CREATE_pop(dcontext, opnd_create_reg(REG_R15))); + /* Fake pop xmm (which we don't use), xflags (which are dead), xip (which is + * dead), the vector, and the error code. */ + APP(ilist, + INSTR_CREATE_lea(dcontext, opnd_create_reg(REG_XSP), + opnd_create_base_disp(REG_XSP, REG_NULL, 0, + simd_slots_size + 4 * sizeof(reg_t), + OPSZ_lea))); + + APP(ilist, INSTR_CREATE_iret(dcontext)); + + pc = instrlist_encode(dcontext, ilist, pc, true); + instrlist_clear_and_destroy(dcontext, ilist); + return pc; +} + +/* + push $vector + jmp common_vector_entry_pc +*/ +byte * +emit_vector_entry(dcontext_t *dcontext, byte *common_vector_entry_pc, + interrupt_vector_t vector, byte *pc) { + instrlist_t* ilist = instrlist_create(dcontext); + if (!vector_has_error_code(vector)) { + APP(ilist, INSTR_CREATE_push_imm(dcontext, + OPND_CREATE_INT32(MAGIC_FAKE_ERROR))); + } + APP(ilist, INSTR_CREATE_push_imm(dcontext, OPND_CREATE_INT32(vector))); + APP(ilist, INSTR_CREATE_jmp(dcontext, + opnd_create_pc(common_vector_entry_pc))); + pc = instrlist_encode(dcontext, ilist, pc, false); + instrlist_clear_and_destroy(dcontext, ilist); + return pc; +} +#endif /* LINUX_KERNEL */ + /* If code_buf points to a jmp rel32 returns true and returns the target of * the jmp in jmp_target as if was located at app_loc. */ bool From 7adfa2d0c4fafc9fd5f326d0103eba8de682e5a2 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Fri, 26 Jun 2026 17:58:23 +0000 Subject: [PATCH 133/156] Reformat --- core/arch/arch.c | 12 ++++---- core/arch/arch.h | 9 ++++-- core/arch/x86/emit_utils.c | 62 ++++++++++++++++++++------------------ 3 files changed, 45 insertions(+), 38 deletions(-) diff --git a/core/arch/arch.c b/core/arch/arch.c index fe5acb7d2..20eebf91f 100644 --- a/core/arch/arch.c +++ b/core/arch/arch.c @@ -2040,13 +2040,15 @@ get_do_vmkuw_syscall_entry(dcontext_t *dcontext) #ifdef LINUX_KERNEL cache_pc -get_syscall_entry(dcontext_t *dcontext) { +get_syscall_entry(dcontext_t *dcontext) +{ generated_code_t *code = THREAD_GENCODE(dcontext); return (cache_pc)code->syscall_entry; } cache_pc -get_vector_entry(dcontext_t *dcontext, interrupt_vector_t vector) { +get_vector_entry(dcontext_t *dcontext, interrupt_vector_t vector) +{ generated_code_t *code = THREAD_GENCODE(dcontext); ASSERT(vector >= VECTOR_START && vector < VECTOR_END); return (cache_pc)code->vector_entry[vector - VECTOR_START]; @@ -2063,10 +2065,8 @@ vector_has_error_code(interrupt_vector_t vector) case VECTOR_STACK_FAULT: case VECTOR_GENERAL_PROTECTION: case VECTOR_PAGE_FAULT: - case VECTOR_ALIGNMENT_CHECK: - return true; - default: - return false; + case VECTOR_ALIGNMENT_CHECK: return true; + default: return false; } } diff --git a/core/arch/arch.h b/core/arch/arch.h index 571e5f9bd..a9e2cf6b8 100644 --- a/core/arch/arch.h +++ b/core/arch/arch.h @@ -1275,11 +1275,14 @@ emit_do_syscall(dcontext_t *dcontext, generated_code_t *code, byte *pc, #ifdef LINUX_KERNEL # define VECTOR_ENTRY_CODE_SIZE (2 * PUSH_IMM32_LENGTH + JMP_LONG_LENGTH) byte * -emit_syscall_entry(dcontext_t *dcontext, cache_pc fcache_return, app_pc target, cache_pc pc); +emit_syscall_entry(dcontext_t *dcontext, cache_pc fcache_return, app_pc target, + cache_pc pc); byte * -emit_common_vector_entry(dcontext_t *dcontext, byte *tls_base, interrupt_handler_t handler, cache_pc pc); +emit_common_vector_entry(dcontext_t *dcontext, byte *tls_base, + interrupt_handler_t handler, cache_pc pc); byte * -emit_vector_entry(dcontext_t *dcontext, byte *common_vector_entry_pc, interrupt_vector_t vector, cache_pc pc); +emit_vector_entry(dcontext_t *dcontext, byte *common_vector_entry_pc, + interrupt_vector_t vector, cache_pc pc); #endif #ifdef AARCH64 diff --git a/core/arch/x86/emit_utils.c b/core/arch/x86/emit_utils.c index da72b61c7..65e4d0401 100644 --- a/core/arch/x86/emit_utils.c +++ b/core/arch/x86/emit_utils.c @@ -517,10 +517,9 @@ insert_inlined_ibl(dcontext_t *dcontext, fragment_t *f, linkstub_t *l, byte *pc, } else { insert_relative_target(start_pc + ibl_code->inline_linkedjmp_offs, linked_exit_target, NOT_HOT_PATCHABLE); - insert_relative_target( - start_pc + ibl_code->inline_unlink_offs + - 1 /* skip jmp opcode: see emit_inline_ibl_stub XXX */, - unlinked_exit_target, NOT_HOT_PATCHABLE); + /* Skip 1-byte jmp opcode: see emit_inline_ibl_stub XXX. */ + byte *unlink_disp = start_pc + ibl_code->inline_unlink_offs + 1; + insert_relative_target(unlink_disp, unlinked_exit_target, NOT_HOT_PATCHABLE); } return start_pc + ibl_code->inline_stub_length; @@ -3164,14 +3163,17 @@ fill_with_nops(dr_isa_mode_t isa_mode, byte *addr, size_t size) jmp unexpected_return */ byte * -emit_syscall_entry(dcontext_t *dcontext, cache_pc fcache_return, app_pc target, cache_pc pc) { +emit_syscall_entry(dcontext_t *dcontext, cache_pc fcache_return, app_pc target, + cache_pc pc) +{ instr_t *swapgs = instr_create(dcontext); - /* TODO i#31: If Kernel Indirect Branch Tracking (IBT) is enabled, the first instruction - * at target (entry_SYSCALL_64) is endbr64 (0xf3 0x0f 0x1e 0xfa). Skip it + /* TODO i#31: If Kernel Indirect Branch Tracking (IBT) is enabled, the first + * instruction at target (entry_SYSCALL_64) is endbr64 (0xf3 0x0f 0x1e 0xfa). Skip it * since endbr64 is not yet implemented in DynamoRIO's opcode tables. */ - if (target[0] == 0xf3 && target[1] == 0x0f && target[2] == 0x1e && target[3] == 0xfa) { + if (target[0] == 0xf3 && target[1] == 0x0f && target[2] == 0x1e && + target[3] == 0xfa) { target += 4; } @@ -3180,7 +3182,7 @@ emit_syscall_entry(dcontext_t *dcontext, cache_pc fcache_return, app_pc target, instrlist_t *ilist = instrlist_create(dcontext); APP(ilist, swapgs); - /* Save XAX and XDI. Get dcontext into XDI. */ + /* Save XAX and XDI. Get dcontext into XDI. */ append_shared_get_dcontext(dcontext, ilist, true /* save_xdi */); APP(ilist, SAVE_TO_TLS(dcontext, REG_XAX, TLS_XAX_SLOT)); /* dcontext->next_tag = target */ @@ -3240,10 +3242,11 @@ append_push_mcontext(dcontext_t *dcontext, int extra_stack, instrlist_t *ilist) APP(ilist, INSTR_CREATE_push_imm(dcontext, OPND_CREATE_INT32(0))); APP(ilist, INSTR_CREATE_RAW_pushf(dcontext)); ASSERT(!preserve_xmm_caller_saved()); - APP(ilist, INSTR_CREATE_lea( - dcontext, opnd_create_reg(REG_XSP), - opnd_create_base_disp(REG_XSP, REG_NULL, 0, -simd_slots_size, OPSZ_lea))); -#ifdef X64 + APP(ilist, + INSTR_CREATE_lea( + dcontext, opnd_create_reg(REG_XSP), + opnd_create_base_disp(REG_XSP, REG_NULL, 0, -simd_slots_size, OPSZ_lea))); +# ifdef X64 APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_R15))); APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_R14))); APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_R13))); @@ -3252,7 +3255,7 @@ append_push_mcontext(dcontext_t *dcontext, int extra_stack, instrlist_t *ilist) APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_R10))); APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_R9))); APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_R8))); -#endif +# endif APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_XAX))); APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_XCX))); APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_XDX))); @@ -3262,15 +3265,17 @@ append_push_mcontext(dcontext_t *dcontext, int extra_stack, instrlist_t *ilist) APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_XSI))); APP(ilist, INSTR_CREATE_push(dcontext, opnd_create_reg(REG_XDI))); /* We pushed the wrong value for rsp. Fix that. */ - APP(ilist, INSTR_CREATE_lea( - dcontext, opnd_create_reg(REG_XAX), - opnd_create_base_disp(REG_XSP, REG_NULL, 0, - sizeof(priv_mcontext_t) + extra_stack, OPSZ_lea))); - APP(ilist, INSTR_CREATE_mov_st( - dcontext, - opnd_create_base_disp(REG_XSP, REG_NULL, 0, - offsetof(priv_mcontext_t, xsp), OPSZ_PTR), - opnd_create_reg(REG_XAX))); + APP(ilist, + INSTR_CREATE_lea(dcontext, opnd_create_reg(REG_XAX), + opnd_create_base_disp(REG_XSP, REG_NULL, 0, + sizeof(priv_mcontext_t) + extra_stack, + OPSZ_lea))); + APP(ilist, + INSTR_CREATE_mov_st(dcontext, + opnd_create_base_disp(REG_XSP, REG_NULL, 0, + offsetof(priv_mcontext_t, xsp), + OPSZ_PTR), + opnd_create_reg(REG_XAX))); } /* @@ -3496,15 +3501,14 @@ emit_common_vector_entry(dcontext_t *dcontext, byte *tls_base, */ byte * emit_vector_entry(dcontext_t *dcontext, byte *common_vector_entry_pc, - interrupt_vector_t vector, byte *pc) { - instrlist_t* ilist = instrlist_create(dcontext); + interrupt_vector_t vector, byte *pc) +{ + instrlist_t *ilist = instrlist_create(dcontext); if (!vector_has_error_code(vector)) { - APP(ilist, INSTR_CREATE_push_imm(dcontext, - OPND_CREATE_INT32(MAGIC_FAKE_ERROR))); + APP(ilist, INSTR_CREATE_push_imm(dcontext, OPND_CREATE_INT32(MAGIC_FAKE_ERROR))); } APP(ilist, INSTR_CREATE_push_imm(dcontext, OPND_CREATE_INT32(vector))); - APP(ilist, INSTR_CREATE_jmp(dcontext, - opnd_create_pc(common_vector_entry_pc))); + APP(ilist, INSTR_CREATE_jmp(dcontext, opnd_create_pc(common_vector_entry_pc))); pc = instrlist_encode(dcontext, ilist, pc, false); instrlist_clear_and_destroy(dcontext, ilist); return pc; From 81c266f115fc2af08ad9ad01acef5c68c16e18c6 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 29 Jun 2026 17:14:06 +0000 Subject: [PATCH 134/156] Add missing include --- core/arch/x86/emit_utils.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/arch/x86/emit_utils.c b/core/arch/x86/emit_utils.c index 65e4d0401..0d1208f93 100644 --- a/core/arch/x86/emit_utils.c +++ b/core/arch/x86/emit_utils.c @@ -51,6 +51,10 @@ #include "decode_private.h" +#ifdef LINUX_KERNEL +# include "msr.h" +#endif + #define PRE instrlist_meta_preinsert #define APP instrlist_meta_append From e79dedd585a9d54ae1ac07263ea74ad420bd4e87 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 29 Jun 2026 18:03:58 +0000 Subject: [PATCH 135/156] Port was_kernel_interrupted from drk branch --- core/arch/arch.c | 6 ++++++ core/arch/arch_exports.h | 23 ++++++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/core/arch/arch.c b/core/arch/arch.c index 20eebf91f..1db276a1a 100644 --- a/core/arch/arch.c +++ b/core/arch/arch.c @@ -2076,6 +2076,12 @@ vector_is_synchronous(interrupt_vector_t vector) ASSERT(vector >= VECTOR_START && vector < VECTOR_END); return vector >= VECTOR_EXCEPTION_START && vector < VECTOR_EXCEPTION_END; } + +bool +was_kernel_interrupted(interrupt_stack_frame_t *frame) +{ + return (frame->cs & 3) == 0; +} #endif cache_pc diff --git a/core/arch/arch_exports.h b/core/arch/arch_exports.h index 0ab6d2292..410d744fa 100644 --- a/core/arch/arch_exports.h +++ b/core/arch/arch_exports.h @@ -1917,6 +1917,16 @@ typedef enum { # define MAGIC_FAKE_ERROR 0xfffffffffbadbeef +/* Returns true if the hardware normally pushes an error code on this vector's + * interrupt stack frame. + */ +bool +vector_has_error_code(interrupt_vector_t vector); + +/* Returns true if the interrupt vector corresponds to a synchronous CPU exception. */ +bool +vector_is_synchronous(interrupt_vector_t vector); + /* The layout of the interrupt stack frame. The stack pointer will point to * error_code. */ typedef struct { @@ -1928,17 +1938,10 @@ typedef struct { reg_t ss; } interrupt_stack_frame_t; -/* Returns true if the hardware normally pushes an error code on this vector's - * interrupt stack frame. - */ -bool -vector_has_error_code(interrupt_vector_t vector); +# define INTERRUPT_STACK_FRAME_ALIGNMENT 0x10 -/* Returns true if the interrupt vector corresponds to a synchronous CPU exception. */ bool -vector_is_synchronous(interrupt_vector_t vector); - -# define INTERRUPT_STACK_FRAME_ALIGNMENT 0x10 +was_kernel_interrupted(interrupt_stack_frame_t *frame); typedef void (*interrupt_handler_t)(interrupt_stack_frame_t *, priv_mcontext_t *, interrupt_vector_t); @@ -1950,8 +1953,6 @@ get_syscall_entry(dcontext_t *dcontext); cache_pc get_vector_entry(dcontext_t *dcontext, interrupt_vector_t vector); -bool -vector_is_synchronous(interrupt_vector_t vector); #endif /* LINUX_KERNEL */ #endif /* _ARCH_EXPORTS_H_ */ From f2e04badcfee84c4045a0903fce8d7b70a4c5816 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 29 Jun 2026 18:05:59 +0000 Subject: [PATCH 136/156] Fix typo --- core/kernel_linux/segment_descriptor.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/kernel_linux/segment_descriptor.h b/core/kernel_linux/segment_descriptor.h index 7daf5d3d8..bb0cff09f 100644 --- a/core/kernel_linux/segment_descriptor.h +++ b/core/kernel_linux/segment_descriptor.h @@ -56,7 +56,7 @@ typedef enum { typedef struct { union { struct { - uint32 requestor_privilige_level : 2; + uint32 requestor_privilege_level : 2; table_indicator_t table_indicator : 1; uint32 index : 13; } __attribute__((__packed__)); @@ -70,7 +70,7 @@ ASSERT_TYPE_SIZE(2, segment_selector_t); static inline void segment_selector_decode(int selector, segment_selector_t *output) { - output->requestor_privilige_level = selector & 0x3; + output->requestor_privilege_level = selector & 0x3; output->table_indicator = (selector & 0x4) >> 2; output->index = (selector & 0xfff8) >> 3; } From dcea2cbacc0cf40f211ef727aa899e5bd5355df0 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 29 Jun 2026 19:09:13 +0000 Subject: [PATCH 137/156] Port patch_interrupt/unpatch_interrupt from drk branch --- core/arch/arch_exports.h | 7 +++++++ core/arch/x86/emit_utils.c | 21 +++++++++++++++++++++ core/ir/instr.h | 1 + 3 files changed, 29 insertions(+) diff --git a/core/arch/arch_exports.h b/core/arch/arch_exports.h index 410d744fa..e7fd825aa 100644 --- a/core/arch/arch_exports.h +++ b/core/arch/arch_exports.h @@ -1917,6 +1917,13 @@ typedef enum { # define MAGIC_FAKE_ERROR 0xfffffffffbadbeef +void +patch_interrupt(dcontext_t *dcontext, cache_pc patch_pc, interrupt_vector_t vector, + byte save_buffer[INT_LENGTH]); + +void +unpatch_interrupt(dcontext_t *dcontext, cache_pc patch_pc, byte save_buffer[INT_LENGTH]); + /* Returns true if the hardware normally pushes an error code on this vector's * interrupt stack frame. */ diff --git a/core/arch/x86/emit_utils.c b/core/arch/x86/emit_utils.c index 0d1208f93..96d4da43e 100644 --- a/core/arch/x86/emit_utils.c +++ b/core/arch/x86/emit_utils.c @@ -3517,6 +3517,27 @@ emit_vector_entry(dcontext_t *dcontext, byte *common_vector_entry_pc, instrlist_clear_and_destroy(dcontext, ilist); return pc; } + +void +patch_interrupt(dcontext_t *dcontext, cache_pc patch_pc, interrupt_vector_t vector, + byte save_buffer[INT_LENGTH]) +{ + memcpy(save_buffer, patch_pc, INT_LENGTH); + byte *write_pc = vmcode_get_writable_addr(patch_pc); + write_pc[0] = INTN_OPCODE; + ASSERT(!vector_has_error_code(vector)); + ASSERT_TRUNCATE(write_pc[1], byte, vector); + write_pc[1] = (byte)vector; +} + +void +unpatch_interrupt(dcontext_t *dcontext, cache_pc patch_pc, byte save_buffer[INT_LENGTH]) +{ + ASSERT(patch_pc[0] == INTN_OPCODE); + ASSERT(!vector_has_error_code(patch_pc[1])); + byte *write_pc = vmcode_get_writable_addr(patch_pc); + memcpy(write_pc, save_buffer, INT_LENGTH); +} #endif /* LINUX_KERNEL */ /* If code_buf points to a jmp rel32 returns true and returns the target of diff --git a/core/ir/instr.h b/core/ir/instr.h index c193897c3..41971bf4f 100644 --- a/core/ir/instr.h +++ b/core/ir/instr.h @@ -858,6 +858,7 @@ enum { /* XXX: vs RAW_OPCODE_* enum */ JECXZ_OPCODE = 0xe3, JMP_SHORT_OPCODE = 0xeb, JMP_OPCODE = 0xe9, + INTN_OPCODE = 0xcd, JNE_OPCODE_1 = 0x0f, SAHF_OPCODE = 0x9e, LAHF_OPCODE = 0x9f, From c8a88ace1fad973e2586664fc0a0942b10e15ee8 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 29 Jun 2026 22:15:25 +0000 Subject: [PATCH 138/156] Port ibl related definitions and function from drk --- core/arch/arch.c | 50 ++++++++++++++++++ core/arch/arch.h | 26 ++++++++- core/arch/arch_exports.h | 7 +++ core/arch/emit_utils_shared.c | 38 +++++++++++--- core/arch/x86/emit_utils.c | 99 +++++++++++++++++++++++++++++++++++ core/dispatch.c | 11 ++++ core/fragment.c | 2 + core/lib/statsx.h | 1 + core/link.c | 8 +++ core/link.h | 2 + 10 files changed, 237 insertions(+), 7 deletions(-) diff --git a/core/arch/arch.c b/core/arch/arch.c index 1db276a1a..e1928473f 100644 --- a/core/arch/arch.c +++ b/core/arch/arch.c @@ -993,12 +993,30 @@ emit_ibl_routine_and_template(dcontext_t *dcontext, generated_code_t *code, byte pc = emit_indirect_branch_lookup(dcontext, code, pc, fcache_return_pc, target_trace_table, inline_ibl_head, ibl_code); + ibl_code->indirect_branch_lookup_routine_end = pc; if (inline_ibl_head) { /* create the inlined ibl template */ pc = check_size_and_cache_line(isa_mode, code, pc); pc = emit_inline_ibl_stub(dcontext, pc, ibl_code, target_trace_table); } + pc = check_size_and_cache_line(isa_mode, code, pc); + ibl_code->found_unlinked = pc; + pc = emit_ibl_found_unlinked_code(dcontext, pc, fcache_return_pc, ibl_code, false, + false); + pc = check_size_and_cache_line(isa_mode, code, pc); + ibl_code->found_unlinked_prefix = pc; + pc = emit_ibl_found_unlinked_code(dcontext, pc, fcache_return_pc, ibl_code, false, + true); + pc = check_size_and_cache_line(isa_mode, code, pc); + ibl_code->found_unlinked_eflags = pc; + pc = emit_ibl_found_unlinked_code(dcontext, pc, fcache_return_pc, ibl_code, true, + false); + pc = check_size_and_cache_line(isa_mode, code, pc); + ibl_code->found_unlinked_eflags_prefix = pc; + pc = emit_ibl_found_unlinked_code(dcontext, pc, fcache_return_pc, ibl_code, true, + true); + ibl_code->far_ibl = pc; pc = emit_far_ibl( dcontext, pc, ibl_code, @@ -2646,6 +2664,38 @@ get_ibl_routine_code(dcontext_t *dcontext, ibl_branch_type_t branch_type, : GENCODE_FROM_DCONTEXT)); } +ibl_code_t * +get_ibl_code_from_routine_pc(dcontext_t *dcontext, cache_pc pc) +{ + ibl_source_fragment_type_t source_fragment_type; + ibl_branch_type_t branch_type; +#if defined(X86) && defined(X64) + gencode_mode_t mode; +#endif + + for (source_fragment_type = IBL_SOURCE_TYPE_START; + source_fragment_type < IBL_SOURCE_TYPE_END; source_fragment_type++) { + for (branch_type = IBL_BRANCH_TYPE_START; branch_type < IBL_BRANCH_TYPE_END; + branch_type++) { +#if defined(X86) && defined(X64) + for (mode = GENCODE_X64; mode <= GENCODE_X86_TO_X64; mode++) { +#endif + ibl_code_t *code = + get_ibl_routine_code_internal(dcontext, source_fragment_type, + branch_type _IF_X86_64(mode)); + if (code != NULL && code->initialized && + pc >= code->indirect_branch_lookup_routine && + pc < code->indirect_branch_lookup_routine_end) { + return code; + } +#if defined(X86) && defined(X64) + } +#endif + } + } + return NULL; +} + #ifdef WINDOWS /* XXX We support a private and shared fragments simultaneously targeting * shared syscall -- -shared_fragment_shared_syscalls must be on and both diff --git a/core/arch/arch.h b/core/arch/arch.h index a9e2cf6b8..a0cce0072 100644 --- a/core/arch/arch.h +++ b/core/arch/arch.h @@ -834,12 +834,25 @@ typedef struct patch_entry_t { negative offsets are from end of instruction */ } patch_entry_t; +#define MAX_IBL_FOUND_EXITS 2 + +typedef struct ibl_found_exit_t { + byte *jmp_pc; + int original_jmp_length; + byte original_jmp_code[MAX_INSTR_LENGTH]; + /* True iff this exit targets fragment prefixes. */ + bool targets_prefix; + /* True iff this exit restores eflags. */ + bool restored_eflags; +} ibl_found_exit_t; + enum { MAX_PATCH_ENTRIES = #ifdef HASHTABLE_STATISTICS 6 + /* will need more only for statistics */ #endif - 7, /* we use 5 normally, 7 w/ -atomic_inlined_linking and inlining */ + 7 + /* we use 5 normally, 7 w/ -atomic_inlined_linking and inlining */ + MAX_IBL_FOUND_EXITS, /* Patch entry flags */ /* Patch offset entries for dynamic updates from input variables */ /* use computed address if set, value at address otherwise */ @@ -910,6 +923,13 @@ typedef struct ibl_code_t { far_ref_t far_jmp_unlinked_opnd; #endif byte *unlinked_ibl_entry; + byte *found_unlinked; + byte *found_unlinked_eflags; + byte *found_unlinked_prefix; + byte *found_unlinked_eflags_prefix; + int num_ibl_found_exits; + ibl_found_exit_t ibl_found_exits[MAX_IBL_FOUND_EXITS]; + byte *indirect_branch_lookup_routine_end; byte *target_delete_entry; uint ibl_routine_length; /* offsets into ibl routine */ @@ -1229,6 +1249,10 @@ byte * emit_indirect_branch_lookup(dcontext_t *dcontext, generated_code_t *code, byte *pc, byte *fcache_return_pc, bool target_trace_table, bool inline_ibl_head, ibl_code_t *ibl_code); +byte * +emit_ibl_found_unlinked_code(dcontext_t *dcontext, byte *pc, byte *fcache_return_pc, + ibl_code_t *ibl_code, bool restore_eflags, + bool include_prefix); void update_indirect_branch_lookup(dcontext_t *dcontext); bool diff --git a/core/arch/arch_exports.h b/core/arch/arch_exports.h index e7fd825aa..fe1312be2 100644 --- a/core/arch/arch_exports.h +++ b/core/arch/arch_exports.h @@ -99,6 +99,7 @@ typedef enum { struct _fragment_entry_t; /* in fragment.h */ struct _ibl_table_t; /* in fragment.h */ +struct ibl_code_t; /* in arch.h */ /* Scratch space and state required to be easily accessible from * in-cache indirect branch lookup routines, store in thread-local storage. @@ -1239,6 +1240,12 @@ link_indirect_exit(dcontext_t *dcontext, fragment_t *f, linkstub_t *l, bool hot_ void unlink_indirect_exit(dcontext_t *dcontext, fragment_t *f, linkstub_t *l); void +unlink_ibl_routine(dcontext_t *dcontext, cache_pc interrupted_ibl_pc); +void +link_ibl_routine(dcontext_t *dcontext, cache_pc interrupted_ibl_pc); +struct ibl_code_t * +get_ibl_code_from_routine_pc(dcontext_t *dcontext, cache_pc pc); +void insert_fragment_prefix(dcontext_t *dcontext, fragment_t *f); int fragment_prefix_size(uint flags); diff --git a/core/arch/emit_utils_shared.c b/core/arch/emit_utils_shared.c index 0b8adbf45..99c6d4e04 100644 --- a/core/arch/emit_utils_shared.c +++ b/core/arch/emit_utils_shared.c @@ -3163,6 +3163,7 @@ append_ibl_found(dcontext_t *dcontext, instrlist_t *ilist, ibl_code_t *ibl_code, /*>>> RESTORE_FROM_UPCONTEXT xbx_OFFSET,%xbx */ /*>>> jmp *FRAGMENT_START_PC_OFFS(%xcx) */ instr_t *inst = NULL; + intrt_t *final_jmp = NULL; IF_X86_64(bool x86_to_x64_ibl_opt = (ibl_code->x86_to_x64_mode && DYNAMO_OPTION(x86_to_x64_ibl_opt));) @@ -3257,9 +3258,10 @@ append_ibl_found(dcontext_t *dcontext, instrlist_t *ilist, ibl_code_t *ibl_code, #if defined(AARCH64) || defined(RISCV64) ASSERT_NOT_IMPLEMENTED(false); /* TODO i#1569 i#3544 */ #else - APP(ilist, + final_jmp = XINST_CREATE_jump_mem(dcontext, - OPND_CREATE_MEMPTR(SCRATCH_REG2, start_pc_offset))); + OPND_CREATE_MEMPTR(SCRATCH_REG2, start_pc_offset)); + APP(ilist, final_jmp); #endif } else { /* There is no prefix so we must restore all and jmp through memory: @@ -3281,10 +3283,11 @@ append_ibl_found(dcontext_t *dcontext, instrlist_t *ilist, ibl_code_t *ibl_code, RESTORE_FROM_TLS(dcontext, SCRATCH_REG2, MANGLE_XCX_SPILL_SLOT)); } else APP(ilist, RESTORE_FROM_DC(dcontext, SCRATCH_REG2, SCRATCH_REG2_OFFS)); - APP(ilist, + final_jmp = XINST_CREATE_jump_mem( dcontext, - OPND_DC_FIELD(absolute, dcontext, OPSZ_PTR, SCRATCH_REG2_OFFS))); + OPND_DC_FIELD(absolute, dcontext, OPSZ_PTR, SCRATCH_REG2_OFFS)); + APP(ilist, final_jmp); #elif defined(AARCH64) ASSERT_NOT_IMPLEMENTED(false); /* TODO i#1569: NYI on AArch64 */ #elif defined(ARM) @@ -3304,13 +3307,36 @@ append_ibl_found(dcontext_t *dcontext, instrlist_t *ilist, ibl_code_t *ibl_code, #if defined(AARCH64) || defined(RISCV64) ASSERT_NOT_IMPLEMENTED(false); /* TODO i#1569 i#3544 */ #else - APP(ilist, + final_jmp = XINST_CREATE_jump_mem(dcontext, - OPND_TLS_FIELD(INDIRECT_STUB_SPILL_SLOT))); + OPND_TLS_FIELD(INDIRECT_STUB_SPILL_SLOT)); + APP(ilist, final_jmp); #endif } } + inst = final_jmp; +#ifdef X86 + if (final_jmp != NULL) { + ibl_found_exit_t *exit; + ASSERT(ibl_code->num_ibl_found_exits < MAX_IBL_FOUND_EXITS); + exit = &ibl_code->ibl_found_exits[ibl_code->num_ibl_found_exits]; + ibl_code->num_ibl_found_exits += 1; + add_patch_marker(patch, final_jmp, PATCH_ASSEMBLE_ABSOLUTE, 0, + (ptr_uint_t *)&exit->jmp_pc); + exit->targets_prefix = target_prefix; + exit->restored_eflags = restore_eflags; + exit->original_jmp_length = instr_length(dcontext, final_jmp); + ASSERT(exit->original_jmp_length <= MAX_INSTR_LENGTH); + if (exit->original_jmp_length < JMP_LONG_LENGTH) { + APP(ilist, INSTR_CREATE_nopNbyte(dcontext, + JMP_LONG_LENGTH - exit->original_jmp_length)); + } + memset(exit->original_jmp_code, 0x90, sizeof(exit->original_jmp_code)); + instr_encode(dcontext, final_jmp, exit->original_jmp_code); + } +#endif + if (fragment_found != NULL) *fragment_found = inst; } diff --git a/core/arch/x86/emit_utils.c b/core/arch/x86/emit_utils.c index 96d4da43e..085011113 100644 --- a/core/arch/x86/emit_utils.c +++ b/core/arch/x86/emit_utils.c @@ -934,6 +934,59 @@ unlink_indirect_exit(dcontext_t *dcontext, fragment_t *f, linkstub_t *l) #endif } +static byte * +get_ibl_found_unlinked_target(ibl_code_t *ibl_code, ibl_found_exit_t *exit) +{ + if (exit->restored_eflags && exit->targets_prefix) { + return ibl_code->found_unlinked_prefix; + } else if (exit->restored_eflags && !exit->targets_prefix) { + return ibl_code->found_unlinked; + } else if (!exit->restored_eflags && exit->targets_prefix) { + return ibl_code->found_unlinked_eflags_prefix; + } else { /* !exit->restored_eflags && !exit->targets_prefix */ + /* In append_ibl_found, !target_prefix => restore_eflags. */ + ASSERT_NOT_REACHED(); + return ibl_code->found_unlinked_eflags; + } +} + +static void +ibl_linking_common(dcontext_t *dcontext, cache_pc interrupted_ibl_pc, bool link) +{ + int i; + generated_code_t *gencode = THREAD_GENCODE(dcontext); + ibl_code_t *code = get_ibl_code_from_routine_pc(dcontext, interrupted_ibl_pc); + ASSERT(code != NULL); + ASSERT(code->indirect_branch_lookup_routine >= gencode->gen_start_pc && + code->indirect_branch_lookup_routine < gencode->gen_end_pc); + protect_generated_code(gencode, WRITABLE); + for (i = 0; i < code->num_ibl_found_exits; i++) { + ibl_found_exit_t *exit = &code->ibl_found_exits[i]; + if (link) { + memcpy(vmcode_get_writable_addr(exit->jmp_pc), exit->original_jmp_code, + JMP_LONG_LENGTH); + } else { + IF_DEBUG(byte *pc =) + insert_relative_jump(exit->jmp_pc, + get_ibl_found_unlinked_target(code, exit), false); + ASSERT(pc - exit->jmp_pc == JMP_LONG_LENGTH); + } + } + protect_generated_code(gencode, READONLY); +} + +void +unlink_ibl_routine(dcontext_t *dcontext, cache_pc interrupted_ibl_pc) +{ + ibl_linking_common(dcontext, interrupted_ibl_pc, false /* unlink */); +} + +void +link_ibl_routine(dcontext_t *dcontext, cache_pc interrupted_ibl_pc) +{ + ibl_linking_common(dcontext, interrupted_ibl_pc, true /* link */); +} + /******************************************************************************* * COARSE-GRAIN FRAGMENT SUPPORT */ @@ -3092,6 +3145,52 @@ emit_indirect_branch_lookup(dcontext_t *dcontext, generated_code_t *code, byte * return pc + ibl_code->ibl_routine_length; } +byte * +emit_ibl_found_unlinked_code(dcontext_t *dcontext, byte *pc, byte *fcache_return_pc, + ibl_code_t *ibl_code, bool restore_eflags, + bool include_prefix) +{ + instrlist_t *ilist = instrlist_create(dcontext); + bool absolute = !ibl_code->thread_shared_routine; + IF_X86_64(bool x86_to_x64_ibl_opt = + (ibl_code->x86_to_x64_mode && DYNAMO_OPTION(x86_to_x64_ibl_opt));) + if (absolute) { + ASSERT_NOT_IMPLEMENTED(false); + return NULL; + } + + if (restore_eflags || include_prefix) { + insert_restore_eflags(dcontext, ilist, NULL /* append */, 0, IBL_EFLAGS_IN_TLS(), + !absolute _IF_X64(x86_to_x64_ibl_opt)); + } + + APP(ilist, SAVE_TO_TLS(dcontext, REG_XAX, DIRECT_STUB_SPILL_SLOT)); + + if (include_prefix) { + APP(ilist, + INSTR_CREATE_mov_ld(dcontext, opnd_create_reg(REG_XAX), + OPND_CREATE_MEMPTR(REG_XCX, HASHLOOKUP_START_PC_OFFS))); + APP(ilist, RESTORE_FROM_TLS(dcontext, REG_XCX, MANGLE_XCX_SPILL_SLOT)); + } else { + APP(ilist, RESTORE_FROM_TLS(dcontext, REG_XAX, INDIRECT_STUB_SPILL_SLOT)); + } + + append_shared_get_dcontext(dcontext, ilist, true /* save xdi to scratch */); + + APP(ilist, SAVE_TO_DC(dcontext, REG_XAX, NEXT_TAG_OFFSET)); + APP(ilist, + INSTR_CREATE_mov_imm( + dcontext, opnd_create_reg(REG_XAX), + OPND_CREATE_INTPTR((ptr_uint_t)get_ibl_unlinked_found_linkstub()))); + + append_shared_restore_dcontext_reg(dcontext, ilist); + APP(ilist, INSTR_CREATE_jmp(dcontext, opnd_create_pc(fcache_return_pc))); + + pc = instrlist_encode(dcontext, ilist, pc, false /* no instr targets */); + instrlist_clear_and_destroy(dcontext, ilist); + return pc; +} + void relink_special_ibl_xfer(dcontext_t *dcontext, int index, ibl_entry_point_type_t entry_type, ibl_branch_type_t ibl_type) diff --git a/core/dispatch.c b/core/dispatch.c index 84db3c506..e0fa9af6c 100644 --- a/core/dispatch.c +++ b/core/dispatch.c @@ -1203,6 +1203,12 @@ dispatch_exit_fcache(dcontext_t *dcontext) * we'll keep coming back here on hits in the outdated table. */ fragment_update_ibl_tables(dcontext); + } else if (dcontext->last_exit == get_ibl_unlinked_found_linkstub()) { + fragment_t *ibl_target, wrapper; + ASSERT(in_fcache(dcontext->next_tag)); + ibl_target = fragment_pclookup(dcontext, dcontext->next_tag, &wrapper); + ASSERT(ibl_target != NULL); + dcontext->next_tag = ibl_target->tag; } /* ref bug 2323, we need monitor to restore last fragment now, @@ -1403,6 +1409,11 @@ dispatch_exit_fcache_stats(dcontext_t *dcontext) STATS_INC(num_exits_ibl_deleted); KSWITCH_STOP_NOT_PROPAGATED(fcache_default); return; + } else if (dcontext->last_exit == get_ibl_unlinked_found_linkstub()) { + LOG(THREAD, LOG_DISPATCH, 2, "Exit from interrupt in ibl hit in ibl\n"); + STATS_INC(num_exits_ibl_unlinked_found); + KSWITCH_STOP_NOT_PROPAGATED(fcache_default); + return; } else if (dcontext->last_exit == get_asynch_linkstub()) { LOG(THREAD, LOG_DISPATCH, 2, "Exit from asynch event\n"); STATS_INC(num_exits_asynch); diff --git a/core/fragment.c b/core/fragment.c index aaa68285e..8703d68e9 100644 --- a/core/fragment.c +++ b/core/fragment.c @@ -4289,6 +4289,8 @@ fragment_add_ibl_target(dcontext_t *dcontext, app_pc tag, ibl_branch_type_t bran } else if (!INTERNAL_OPTION(link_ibl)) { reason = "-no_link_ibl prevents ibl"; STATS_INC(num_ibt_exit_nolink); + } else if (dcontext->last_exit == get_ibl_unlinked_found_linkstub()) { + reason = "IBL routine unlinked for interrupt."; } else if (DYNAMO_OPTION(disable_traces) && !TEST(FRAG_LINKED_OUTGOING, dcontext->last_fragment->flags)) { reason = "IBL fragment unlinked in signal handler"; diff --git a/core/lib/statsx.h b/core/lib/statsx.h index 2a4af4ee5..2d8aeff4a 100644 --- a/core/lib/statsx.h +++ b/core/lib/statsx.h @@ -686,6 +686,7 @@ STATS_DEF("Fcache exits, fine targeting non-th coarse", num_exits_fine2non_th_co STATS_DEF("Fcache exits, system call executions", num_exits_syscalls) STATS_DEF("Fcache exits, flushed due to code mod", num_exits_code_mod_flush) STATS_DEF("Fcache exits, deleted but hit in ibl", num_exits_ibl_deleted) +STATS_DEF("Fcache exits, interrupt in ibl hit in ibl", num_exits_ibl_unlinked_found) STATS_DEF("Fcache exits, asynch", num_exits_asynch) STATS_DEF("Fcache exits, native_exec executions", num_exits_native_exec) STATS_DEF("Fcache exits, native_exec syscalls", num_exits_native_exec_syscall) diff --git a/core/link.c b/core/link.c index 6111a2083..066f80eae 100644 --- a/core/link.c +++ b/core/link.c @@ -161,6 +161,7 @@ static #endif const linkstub_t linkstub_selfmod = { LINK_FAKE, 0 }; static const linkstub_t linkstub_ibl_deleted = { LINK_FAKE, 0 }; +static const linkstub_t linkstub_ibl_unlinked_found = { LINK_FAKE, 0 }; static const linkstub_t linkstub_asynch = { LINK_FAKE, 0 }; static const linkstub_t linkstub_native_exec = { LINK_FAKE, 0 }; /* this one we give the flag LINK_NI_SYSCALL for executing a syscall in d_r_dispatch() */ @@ -745,6 +746,12 @@ get_ibl_deleted_linkstub() return &linkstub_ibl_deleted; } +const linkstub_t * +get_ibl_unlinked_found_linkstub() +{ + return &linkstub_ibl_unlinked_found; +} + const linkstub_t * get_asynch_linkstub() { @@ -823,6 +830,7 @@ is_ibl_sourceless_linkstub(const linkstub_t *l) return (l == &linkstub_ibl_trace_ret || l == &linkstub_ibl_trace_jmp || l == &linkstub_ibl_trace_call || l == &linkstub_ibl_bb_ret || l == &linkstub_ibl_bb_jmp || l == &linkstub_ibl_bb_call || + l == &linkstub_ibl_unlinked_found || is_special_ibl_linkstub(l)); } diff --git a/core/link.h b/core/link.h index 5cd374765..72ffd96d5 100644 --- a/core/link.h +++ b/core/link.h @@ -497,6 +497,8 @@ extern const linkstub_t linkstub_selfmod; #endif const linkstub_t * get_ibl_deleted_linkstub(void); +const linkstub_t * +get_ibl_unlinked_found_linkstub(void); /* This is used for Windows APC, callback, etc. and Linux sigreturn, forge fault, etc. */ const linkstub_t * get_asynch_linkstub(void); From d21462ee1c6aadf5201578c94655c3b19045fbf7 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 29 Jun 2026 22:16:04 +0000 Subject: [PATCH 139/156] Replace deprecated functions --- core/arch/arch.c | 1 + core/arch/emit_utils_shared.c | 2 +- core/arch/x86/emit_utils.c | 8 ++++---- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/core/arch/arch.c b/core/arch/arch.c index e1928473f..62d715e7a 100644 --- a/core/arch/arch.c +++ b/core/arch/arch.c @@ -990,6 +990,7 @@ emit_ibl_routine_and_template(dcontext_t *dcontext, generated_code_t *code, byte ibl_code->thread_shared_routine = thread_shared; ibl_code->branch_type = branch_type; ibl_code->source_fragment_type = source_type; + ibl_code->num_ibl_found_exits = 0; pc = emit_indirect_branch_lookup(dcontext, code, pc, fcache_return_pc, target_trace_table, inline_ibl_head, ibl_code); diff --git a/core/arch/emit_utils_shared.c b/core/arch/emit_utils_shared.c index 99c6d4e04..f943b2c30 100644 --- a/core/arch/emit_utils_shared.c +++ b/core/arch/emit_utils_shared.c @@ -3163,7 +3163,7 @@ append_ibl_found(dcontext_t *dcontext, instrlist_t *ilist, ibl_code_t *ibl_code, /*>>> RESTORE_FROM_UPCONTEXT xbx_OFFSET,%xbx */ /*>>> jmp *FRAGMENT_START_PC_OFFS(%xcx) */ instr_t *inst = NULL; - intrt_t *final_jmp = NULL; + instr_t *final_jmp = NULL; IF_X86_64(bool x86_to_x64_ibl_opt = (ibl_code->x86_to_x64_mode && DYNAMO_OPTION(x86_to_x64_ibl_opt));) diff --git a/core/arch/x86/emit_utils.c b/core/arch/x86/emit_utils.c index 085011113..69ec060dc 100644 --- a/core/arch/x86/emit_utils.c +++ b/core/arch/x86/emit_utils.c @@ -3175,7 +3175,7 @@ emit_ibl_found_unlinked_code(dcontext_t *dcontext, byte *pc, byte *fcache_return APP(ilist, RESTORE_FROM_TLS(dcontext, REG_XAX, INDIRECT_STUB_SPILL_SLOT)); } - append_shared_get_dcontext(dcontext, ilist, true /* save xdi to scratch */); + insert_shared_get_dcontext(dcontext, ilist, NULL, true /* save xdi to scratch */); APP(ilist, SAVE_TO_DC(dcontext, REG_XAX, NEXT_TAG_OFFSET)); APP(ilist, @@ -3183,7 +3183,7 @@ emit_ibl_found_unlinked_code(dcontext_t *dcontext, byte *pc, byte *fcache_return dcontext, opnd_create_reg(REG_XAX), OPND_CREATE_INTPTR((ptr_uint_t)get_ibl_unlinked_found_linkstub()))); - append_shared_restore_dcontext_reg(dcontext, ilist); + insert_shared_restore_dcontext_reg(dcontext, ilist, NULL); APP(ilist, INSTR_CREATE_jmp(dcontext, opnd_create_pc(fcache_return_pc))); pc = instrlist_encode(dcontext, ilist, pc, false /* no instr targets */); @@ -3286,7 +3286,7 @@ emit_syscall_entry(dcontext_t *dcontext, cache_pc fcache_return, app_pc target, instrlist_t *ilist = instrlist_create(dcontext); APP(ilist, swapgs); /* Save XAX and XDI. Get dcontext into XDI. */ - append_shared_get_dcontext(dcontext, ilist, true /* save_xdi */); + insert_shared_get_dcontext(dcontext, ilist, NULL, true /* save_xdi */); APP(ilist, SAVE_TO_TLS(dcontext, REG_XAX, TLS_XAX_SLOT)); /* dcontext->next_tag = target */ APP(ilist, @@ -3300,7 +3300,7 @@ emit_syscall_entry(dcontext_t *dcontext, cache_pc fcache_return, app_pc target, OPND_CREATE_INTPTR(get_syscall_entry_linkstub()))); /* Restore XDI. Don't need to restore XAX because fcache_return does that * for us. */ - append_shared_restore_dcontext_reg(dcontext, ilist); + insert_shared_restore_dcontext_reg(dcontext, ilist, NULL); /* Do fcache_return. */ APP(ilist, INSTR_CREATE_jmp(dcontext, opnd_create_pc(fcache_return))); APP(ilist, INSTR_CREATE_jmp(dcontext, opnd_create_pc((app_pc)unexpected_return))); From 3ac398af289fdd7eee499ab89c88044695fe1c32 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 29 Jun 2026 22:17:40 +0000 Subject: [PATCH 140/156] Reformat --- core/arch/arch.c | 5 ++--- core/arch/emit_utils_shared.c | 19 ++++++++----------- core/arch/x86/emit_utils.c | 4 ++-- core/link.c | 3 +-- 4 files changed, 13 insertions(+), 18 deletions(-) diff --git a/core/arch/arch.c b/core/arch/arch.c index 62d715e7a..e199fb7fc 100644 --- a/core/arch/arch.c +++ b/core/arch/arch.c @@ -2681,9 +2681,8 @@ get_ibl_code_from_routine_pc(dcontext_t *dcontext, cache_pc pc) #if defined(X86) && defined(X64) for (mode = GENCODE_X64; mode <= GENCODE_X86_TO_X64; mode++) { #endif - ibl_code_t *code = - get_ibl_routine_code_internal(dcontext, source_fragment_type, - branch_type _IF_X86_64(mode)); + ibl_code_t *code = get_ibl_routine_code_internal( + dcontext, source_fragment_type, branch_type _IF_X86_64(mode)); if (code != NULL && code->initialized && pc >= code->indirect_branch_lookup_routine && pc < code->indirect_branch_lookup_routine_end) { diff --git a/core/arch/emit_utils_shared.c b/core/arch/emit_utils_shared.c index f943b2c30..ae2d7ef05 100644 --- a/core/arch/emit_utils_shared.c +++ b/core/arch/emit_utils_shared.c @@ -3258,9 +3258,8 @@ append_ibl_found(dcontext_t *dcontext, instrlist_t *ilist, ibl_code_t *ibl_code, #if defined(AARCH64) || defined(RISCV64) ASSERT_NOT_IMPLEMENTED(false); /* TODO i#1569 i#3544 */ #else - final_jmp = - XINST_CREATE_jump_mem(dcontext, - OPND_CREATE_MEMPTR(SCRATCH_REG2, start_pc_offset)); + final_jmp = XINST_CREATE_jump_mem( + dcontext, OPND_CREATE_MEMPTR(SCRATCH_REG2, start_pc_offset)); APP(ilist, final_jmp); #endif } else { @@ -3283,10 +3282,8 @@ append_ibl_found(dcontext_t *dcontext, instrlist_t *ilist, ibl_code_t *ibl_code, RESTORE_FROM_TLS(dcontext, SCRATCH_REG2, MANGLE_XCX_SPILL_SLOT)); } else APP(ilist, RESTORE_FROM_DC(dcontext, SCRATCH_REG2, SCRATCH_REG2_OFFS)); - final_jmp = - XINST_CREATE_jump_mem( - dcontext, - OPND_DC_FIELD(absolute, dcontext, OPSZ_PTR, SCRATCH_REG2_OFFS)); + final_jmp = XINST_CREATE_jump_mem( + dcontext, OPND_DC_FIELD(absolute, dcontext, OPSZ_PTR, SCRATCH_REG2_OFFS)); APP(ilist, final_jmp); #elif defined(AARCH64) ASSERT_NOT_IMPLEMENTED(false); /* TODO i#1569: NYI on AArch64 */ @@ -3308,8 +3305,7 @@ append_ibl_found(dcontext_t *dcontext, instrlist_t *ilist, ibl_code_t *ibl_code, ASSERT_NOT_IMPLEMENTED(false); /* TODO i#1569 i#3544 */ #else final_jmp = - XINST_CREATE_jump_mem(dcontext, - OPND_TLS_FIELD(INDIRECT_STUB_SPILL_SLOT)); + XINST_CREATE_jump_mem(dcontext, OPND_TLS_FIELD(INDIRECT_STUB_SPILL_SLOT)); APP(ilist, final_jmp); #endif } @@ -3329,8 +3325,9 @@ append_ibl_found(dcontext_t *dcontext, instrlist_t *ilist, ibl_code_t *ibl_code, exit->original_jmp_length = instr_length(dcontext, final_jmp); ASSERT(exit->original_jmp_length <= MAX_INSTR_LENGTH); if (exit->original_jmp_length < JMP_LONG_LENGTH) { - APP(ilist, INSTR_CREATE_nopNbyte(dcontext, - JMP_LONG_LENGTH - exit->original_jmp_length)); + APP(ilist, + INSTR_CREATE_nopNbyte(dcontext, + JMP_LONG_LENGTH - exit->original_jmp_length)); } memset(exit->original_jmp_code, 0x90, sizeof(exit->original_jmp_code)); instr_encode(dcontext, final_jmp, exit->original_jmp_code); diff --git a/core/arch/x86/emit_utils.c b/core/arch/x86/emit_utils.c index 69ec060dc..c708f9512 100644 --- a/core/arch/x86/emit_utils.c +++ b/core/arch/x86/emit_utils.c @@ -967,8 +967,8 @@ ibl_linking_common(dcontext_t *dcontext, cache_pc interrupted_ibl_pc, bool link) JMP_LONG_LENGTH); } else { IF_DEBUG(byte *pc =) - insert_relative_jump(exit->jmp_pc, - get_ibl_found_unlinked_target(code, exit), false); + insert_relative_jump(exit->jmp_pc, get_ibl_found_unlinked_target(code, exit), + false); ASSERT(pc - exit->jmp_pc == JMP_LONG_LENGTH); } } diff --git a/core/link.c b/core/link.c index 066f80eae..a4daaf2da 100644 --- a/core/link.c +++ b/core/link.c @@ -830,8 +830,7 @@ is_ibl_sourceless_linkstub(const linkstub_t *l) return (l == &linkstub_ibl_trace_ret || l == &linkstub_ibl_trace_jmp || l == &linkstub_ibl_trace_call || l == &linkstub_ibl_bb_ret || l == &linkstub_ibl_bb_jmp || l == &linkstub_ibl_bb_call || - l == &linkstub_ibl_unlinked_found || - is_special_ibl_linkstub(l)); + l == &linkstub_ibl_unlinked_found || is_special_ibl_linkstub(l)); } const linkstub_t * From ca84a26b016b6b4c572cc9b4ca9b9f74d11267d1 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 29 Jun 2026 23:56:45 +0000 Subject: [PATCH 141/156] Port dr_interrupt_t and related API declarations from drk --- core/lib/dr_events.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/core/lib/dr_events.h b/core/lib/dr_events.h index e86007ede..d4aa3c57b 100644 --- a/core/lib/dr_events.h +++ b/core/lib/dr_events.h @@ -808,6 +808,30 @@ bool dr_unregister_restore_state_ex_event(bool (*func)(void *drcontext, bool restore_memory, dr_restore_state_info_t *info)); +#ifdef LINUX_KERNEL +typedef struct _dr_interrupt_t { + interrupt_stack_frame_t *frame; + interrupt_stack_frame_t *raw_frame; + interrupt_vector_t vector; + dr_mcontext_t *mcontext; +} dr_interrupt_t; + +DR_API +/** + * Registers a callback function for kernel interrupt events. + */ +void +dr_register_interrupt_event(bool (*func)(void *drcontext, dr_interrupt_t *interrupt)); + +DR_API +/** + * Unregister a callback function for kernel interrupt events. \return true if + * unregistration is successful and false if it is not (e.g., \p func was not registered). + */ +bool +dr_unregister_interrupt_event(bool (*func)(void *drcontext, dr_interrupt_t *interrupt)); +#endif + DR_API /** * Registers a callback function for the thread initialization event. From 59e029caf311218fae5bcdf4b7155d93029b7a32 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 30 Jun 2026 00:19:17 +0000 Subject: [PATCH 142/156] Add signature of instrument_interrupt --- core/lib/instrument.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/lib/instrument.h b/core/lib/instrument.h index 0ff396a94..a58394e15 100644 --- a/core/lib/instrument.h +++ b/core/lib/instrument.h @@ -118,7 +118,10 @@ bool instrument_restore_nonfcache_state_prealloc(dcontext_t *dcontext, bool restore_memory, DR_PARAM_INOUT priv_mcontext_t *mcontext, DR_PARAM_OUT dr_mcontext_t *client_mcontext); - +#ifdef LINUX_KERNEL +bool +instrument_interrupt(dcontext_t *dcontext, dr_interrupt_t *interrupt); +#endif module_data_t * copy_module_area_to_module_data(const module_area_t *area); void From 1d2fdd5c79620aa0ec38ba1d5bab939b13c01c8e Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 30 Jun 2026 03:58:19 +0000 Subject: [PATCH 143/156] Add function definitions --- core/lib/instrument.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/core/lib/instrument.c b/core/lib/instrument.c index faf5fd5be..232836c77 100644 --- a/core/lib/instrument.c +++ b/core/lib/instrument.c @@ -256,6 +256,10 @@ static callback_list_t post_syscall_callbacks = { static callback_list_t kernel_xfer_callbacks = { 0, }; +#else +static callback_list_t interrupt_callbacks = { + 0, +}; #endif #ifdef WINDOWS static callback_list_t exception_callbacks = { @@ -877,6 +881,8 @@ free_all_callback_lists(void) free_callback_list(&post_syscall_callbacks); #ifndef LINUX_KERNEL free_callback_list(&kernel_xfer_callbacks); +#else + free_callback_list(&interrupt_callbacks); #endif #ifdef WINDOWS free_callback_list(&exception_callbacks); @@ -1953,6 +1959,39 @@ instrument_restore_nonfcache_state(dcontext_t *dcontext, bool restore_memory, &client_mcontext); } +#ifdef LINUX_KERNEL +void +dr_register_interrupt_event(bool (*func)(void *dcontext, dr_interrupt_t *interrupt)) +{ + if (func == NULL) { + CLIENT_ASSERT(false, "trying to register a NULL callback"); + return; + } + if (!INTERNAL_OPTION(code_api)) { + CLIENT_ASSERT(false, "asking for interrupt event when code_api disabled"); + return; + } + add_callback(&interrupt_callbacks, (void (*)(void))func, true); +} + +bool +dr_unregister_interrupt_event(bool (*func)(void *drcontext, dr_interrupt_t *interrupt)) +{ + return remove_callback(&interrupt_callbacks, (void (*)(void))func, true); +} + +bool +instrument_interrupt(dcontext_t *dcontext, dr_interrupt_t *interrupt) +{ + bool res = true; + if (interrupt_callbacks.num > 0) { + call_all_ret(res, = res &&, , interrupt_callbacks, + bool (*)(void *, dr_interrupt_t *), (void *)dcontext, interrupt); + } + return res; +} +#endif + /* Ask whether to end trace prior to adding next_tag fragment. * Return values: * CUSTOM_TRACE_DR_DECIDES = use standard termination criteria From 58e1da3b5dcb87bccd920e3a4b2bf54d24a4f94a Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 30 Jun 2026 05:01:00 +0000 Subject: [PATCH 144/156] Port clean_call_clear_saved_interrupt_flag from drk --- core/arch/arch_exports.h | 3 +++ core/arch/x86/mangle.c | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/core/arch/arch_exports.h b/core/arch/arch_exports.h index fe1312be2..1e5559fe1 100644 --- a/core/arch/arch_exports.h +++ b/core/arch/arch_exports.h @@ -1967,6 +1967,9 @@ get_syscall_entry(dcontext_t *dcontext); cache_pc get_vector_entry(dcontext_t *dcontext, interrupt_vector_t vector); +void +clean_call_clear_saved_interrupt_flag(dcontext_t *dcontext, byte *sp); + #endif /* LINUX_KERNEL */ #endif /* _ARCH_EXPORTS_H_ */ diff --git a/core/arch/x86/mangle.c b/core/arch/x86/mangle.c index f14504809..399b98ed7 100644 --- a/core/arch/x86/mangle.c +++ b/core/arch/x86/mangle.c @@ -863,6 +863,19 @@ insert_clean_call_with_arg_jmp_if_ret_true(dcontext_t *dcontext, instrlist_t *il instr_set_target(jcc, opnd_create_instr(false_popa)); } +#ifdef LINUX_KERNEL +void +clean_call_clear_saved_interrupt_flag(dcontext_t *dcontext, byte *sp) +{ + priv_mcontext_t *mc = get_priv_mcontext_from_dstack(dcontext); + if (sp <= (byte *)&mc->xflags) { + /* Clean call pushes 0 before it pushes xflags. */ + ASSERT(mc->pc == 0); + mc->xflags &= ~EFLAGS_IF; + } +} +#endif + /* If !precise, encode_pc is treated as +- a page (meant for clients * writing an instrlist to gencode so not sure of exact placement but * within a page). From 45d64a20a7908ade899a0c2c42df6571f9cd5379 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 30 Jun 2026 05:02:46 +0000 Subject: [PATCH 145/156] Handle conversion between priv_mcontext_t and dr_mcontext_t --- core/kernel_linux/os.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/kernel_linux/os.c b/core/kernel_linux/os.c index e3924d2fd..f1771db04 100644 --- a/core/kernel_linux/os.c +++ b/core/kernel_linux/os.c @@ -1090,11 +1090,15 @@ send_interrupt_to_client(dcontext_t *dcontext, interrupt_context_t *interrupt) { bool res; dr_interrupt_t dr_interrupt; + dr_mcontext_t mc; dr_interrupt.frame = &interrupt->frame; dr_interrupt.raw_frame = interrupt->raw_frame; dr_interrupt.vector = interrupt->vector; - dr_interrupt.mcontext = interrupt->mcontext; + dr_mcontext_init(&mc); + priv_mcontext_to_dr_mcontext(&mc, interrupt->mcontext); + dr_interrupt.mcontext = &mc; res = instrument_interrupt(dcontext, &dr_interrupt); + dr_mcontext_to_priv_mcontext(interrupt->mcontext, &mc); return res; } From 4d55d1110e61c7ef83aca0e68b2c9a3eac5732b3 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 30 Jun 2026 17:17:51 +0000 Subject: [PATCH 146/156] Define INSTR_INLINE as static inline in kernel build --- core/ir/instr.h | 4 +++- core/ir/instr_api.h | 4 +++- core/ir/opnd.h | 4 +++- core/ir/opnd_api.h | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/core/ir/instr.h b/core/ir/instr.h index 41971bf4f..1e5a593ea 100644 --- a/core/ir/instr.h +++ b/core/ir/instr.h @@ -68,7 +68,9 @@ struct instr_info_t; */ /* Inlining macro controls. */ #ifndef INSTR_INLINE -# ifdef DR_FAST_IR +# ifdef LINUX_KERNEL +# define INSTR_INLINE static inline +# elif defined(DR_FAST_IR) # define INSTR_INLINE inline # else # define INSTR_INLINE diff --git a/core/ir/instr_api.h b/core/ir/instr_api.h index 9f8548f62..48bd782e4 100644 --- a/core/ir/instr_api.h +++ b/core/ir/instr_api.h @@ -43,7 +43,9 @@ */ #ifndef INSTR_INLINE -# ifdef DR_FAST_IR +# ifdef LINUX_KERNEL +# define INSTR_INLINE static inline +# elif defined(DR_FAST_IR) # define INSTR_INLINE inline # else # define INSTR_INLINE diff --git a/core/ir/opnd.h b/core/ir/opnd.h index c8054023e..a564691f8 100644 --- a/core/ir/opnd.h +++ b/core/ir/opnd.h @@ -81,7 +81,9 @@ */ /* Inlining macro controls. */ #ifndef INSTR_INLINE -# ifdef DR_FAST_IR +# ifdef LINUX_KERNEL +# define INSTR_INLINE static inline +# elif defined(DR_FAST_IR) # define INSTR_INLINE inline # else # define INSTR_INLINE diff --git a/core/ir/opnd_api.h b/core/ir/opnd_api.h index fedf332e6..6da1cdaec 100644 --- a/core/ir/opnd_api.h +++ b/core/ir/opnd_api.h @@ -48,7 +48,9 @@ #endif #ifndef INSTR_INLINE -# ifdef DR_FAST_IR +# ifdef LINUX_KERNEL +# define INSTR_INLINE static inline +# elif defined(DR_FAST_IR) # define INSTR_INLINE inline # else # define INSTR_INLINE From 04d14fdc595d8898e726e6d799cd8e399026b485 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 30 Jun 2026 17:24:31 +0000 Subject: [PATCH 147/156] Fix symbol export handling in kernel builds --- core/globals.h | 4 +++- core/lib/dr_app.h | 2 +- core/lib/globals_api.h | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/core/globals.h b/core/globals.h index 839eb0793..1a0320064 100644 --- a/core/globals.h +++ b/core/globals.h @@ -95,8 +95,10 @@ /* currently we always export statistics structure */ #define DYNAMORIO_STATS_EXPORTS 1 -#ifdef WINDOWS +#if defined(WINDOWS) # define DYNAMORIO_EXPORT __declspec(dllexport) +#elif defined(LINUX_KERNEL) +# define DYNAMORIO_EXPORT /* nothing */ #elif defined(USE_VISIBILITY_ATTRIBUTES) /* PR 262804: we use "protected" instead of "default" to ensure our * own uses won't be preempted. Note that for DR_APP_API in diff --git a/core/lib/dr_app.h b/core/lib/dr_app.h index 058af34de..4c8ae5c08 100644 --- a/core/lib/dr_app.h +++ b/core/lib/dr_app.h @@ -47,7 +47,7 @@ # define DR_APP_API __declspec(dllimport) # endif #else /* UNIX */ -# if defined(DR_APP_EXPORTS) && defined(USE_VISIBILITY_ATTRIBUTES) +# if defined(DR_APP_EXPORTS) && defined(USE_VISIBILITY_ATTRIBUTES) && !defined(LINUX_KERNEL) # define DR_APP_API __attribute__((visibility("default"))) # else # define DR_APP_API diff --git a/core/lib/globals_api.h b/core/lib/globals_api.h index 779117230..415d51ca5 100644 --- a/core/lib/globals_api.h +++ b/core/lib/globals_api.h @@ -164,7 +164,7 @@ typedef char bool; * (in gcc >= 3.4) to not export symbols by default, setting * USE_VISIBILITY_ATTRIBUTES will properly export. */ -# ifdef USE_VISIBILITY_ATTRIBUTES +# if defined(USE_VISIBILITY_ATTRIBUTES) && !defined(LINUX_KERNEL) # define DR_EXPORT __attribute__((visibility("default"))) # else # define DR_EXPORT From 250e5e2d63326e7c2bd65bf2a6392cdbfcff2c35 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 30 Jun 2026 18:08:42 +0000 Subject: [PATCH 148/156] Port signature declaration for os_warm_fcache from drk --- core/os_shared.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/os_shared.h b/core/os_shared.h index c067cea91..c8b1047b6 100644 --- a/core/os_shared.h +++ b/core/os_shared.h @@ -113,6 +113,13 @@ os_heap_init(void); void os_heap_exit(void); +#ifdef LINUX_KERNEL +/* Called on each thread right before dispatching starts. This can be used to + * warm the fragment cache. + */ +void os_warm_fcache(dcontext_t* dcontext); +#endif + /* os provided heap routines */ /* caller is required to handle thread synchronization and to update dynamo vm areas. * size must be PAGE_SIZE-aligned. From 01b4922df0567371f0cc58dbbde001d179529264 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 30 Jun 2026 18:09:37 +0000 Subject: [PATCH 149/156] Port definitions for dr_smp_init/dr_smp_exit from drk --- core/dynamo.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/core/dynamo.c b/core/dynamo.c index 18eab4687..5a4eb3351 100644 --- a/core/dynamo.c +++ b/core/dynamo.c @@ -67,6 +67,13 @@ # include "annotations.h" #endif +#ifdef LINUX_KERNEL +# include "barrier.h" +# include "dynamorio_module_interface.h" +# include "kernel_interface.h" +# include "msr.h" +#endif + #ifdef WINDOWS /* for close handle, duplicate handle, free memory and constants associated with them */ @@ -386,6 +393,99 @@ get_dr_stats(void) return d_r_stats; } +#ifdef LINUX_KERNEL +/* Init barriers */ +static barrier_t before_dynamo_app_init; +static barrier_t after_dynamo_app_init; +static barrier_t before_dynamorio_app_take_over; + +/* Exit barriers */ +static barrier_t main_thread_exit; +static barrier_t other_threads_exit; + +void +dr_pre_smp_init(dr_exports_t *exports, const char *options) +{ + exports->stats_data = &nonshared_stats; + exports->stats_size = sizeof(dr_statistics_t); + kernel_setenv(DYNAMORIO_VAR_OPTIONS, options); + barrier_init(&before_dynamo_app_init, get_num_processors()); + barrier_init(&after_dynamo_app_init, get_num_processors()); + barrier_init(&before_dynamorio_app_take_over, get_num_processors()); + barrier_init(&main_thread_exit, get_num_processors()); + barrier_init(&other_threads_exit, get_num_processors()); +} + +void +cpu_exports_init(dcontext_t *dcontext, dr_cpu_exports_t *exports) +{ +# ifdef KSTATS + if (DYNAMO_OPTION(kstats)) { + exports->kstats_data = &dcontext->thread_kstats->vars_kstats; + exports->kstats_size = sizeof(dcontext->thread_kstats->vars_kstats); + } else { +# endif + exports->kstats_data = NULL; + exports->kstats_size = 0; +# ifdef KSTATS + } +# endif +} + +void +dr_smp_init(dr_cpu_exports_t *exports) +{ + /* Interrupts are disabled at this point. */ + if (barrier_wait(&before_dynamo_app_init)) { + /* barrier_wait only returns true for one thread. We designate this as + * the main thread for initilization. + */ + dynamorio_app_init(); + barrier_wait(&after_dynamo_app_init); + } else { + barrier_wait(&after_dynamo_app_init); + /* The following three lines are called for the main thread by + * dynamorio_app_init. + */ + dynamo_thread_init(NULL, NULL, NULL, false); + ENTERING_DR(); + // instrument_thread_init(get_thread_private_dcontext(), false, false); + } + os_warm_fcache(get_thread_private_dcontext()); + cpu_exports_init(get_thread_private_dcontext(), exports); + barrier_wait(&before_dynamorio_app_take_over); + /* dynamorio_app_take_over needs to be called at this point from another + * module. Otherwise, we would try to cache some DR instructions (i.e., this + * function's implicit return), which DR isn't designed to handle. See + * dynamorio_app_take_over() in dynamorio_module_interface.h. */ +} + +void +dr_smp_exit(void) +{ + DEBUG_DECLARE(int res;) + static bool main_thread_exited = false; + if (barrier_wait(&main_thread_exit)) { + barrier_wait(&other_threads_exit); + barrier_destroy(&before_dynamo_app_init); + barrier_destroy(&after_dynamo_app_init); + barrier_destroy(&before_dynamorio_app_take_over); + barrier_destroy(&main_thread_exit); + barrier_destroy(&other_threads_exit); + IF_DEBUG(res =) dr_app_cleanup(); + ASSERT(res == SUCCESS); + asm volatile("mfence"); + main_thread_exited = true; + } else { + IF_DEBUG(res =) dynamo_thread_exit(); + ASSERT(res == SUCCESS); + barrier_wait(&other_threads_exit); + } + while (!main_thread_exited) { + } +} +#endif + /* initialize per-process dynamo state; this must be called before any * threads are created and before any other API calls are made; * returns zero on success, non-zero on failure From b62c66d3821e57ed34b2ee1087ae4a91b14ef63d Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 30 Jun 2026 18:10:09 +0000 Subject: [PATCH 150/156] Exclude unported functions from being exported --- core/exports.py | 464 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 448 insertions(+), 16 deletions(-) diff --git a/core/exports.py b/core/exports.py index cafc4fadf..63d8dd382 100755 --- a/core/exports.py +++ b/core/exports.py @@ -17,29 +17,461 @@ def check_open(args): def excluded_functions(): return { + "INSTR_CREATE_nop2byte_reg", + "INSTR_CREATE_nop3byte_reg", "__attribute__", - "dr_init", - "dr_smp_exit", + "decode_memory_reference_size", + "disassemble", + "disassemble_from_copy", + "disassemble_set_syntax", + "disassemble_to_buffer", + "disassemble_with_info", + "dr_add_prefixes_to_basic_blocks", + "dr_annotation_pass_pc", + "dr_annotation_register_call", + "dr_annotation_register_return", + "dr_annotation_register_valgrind", + "dr_annotation_set_return_value", + "dr_annotation_unregister_call", + "dr_annotation_unregister_return", + "dr_annotation_unregister_valgrind", + "dr_app_handle_mbr_target", + "dr_client_iterator_hasnext", + "dr_client_iterator_next", + "dr_client_iterator_next_ex", + "dr_client_iterator_start", + "dr_client_iterator_stop", + "dr_client_main", + "dr_client_thread_set_suspendable", + "dr_config_status_code_to_string", + "dr_copy_module_data", + "dr_create_client_thread", + "dr_free_module_data", "dr_get_app_PEB", - "instr_exit_stub_code", - "dr_syscall_get_result", + "dr_get_client_info", + "dr_get_client_info_ex", + "dr_get_config_dir", + "dr_get_isa_mode", + "dr_get_main_module", + "dr_get_proc_address", + "dr_get_proc_address_ex", + "dr_get_stderr_file", + "dr_get_stdin_file", + "dr_get_stdout_file", + "dr_get_vector_length", + "dr_init", + "dr_inject_get_image_name", + "dr_inject_get_process_id", + "dr_inject_prepare_new_process_group", + "dr_inject_prepare_to_attach", + "dr_inject_prepare_to_exec", + "dr_inject_prepare_to_ptrace", + "dr_inject_print_stats", + "dr_inject_process_create", + "dr_inject_process_exit", + "dr_inject_process_inject", + "dr_inject_process_run", + "dr_inject_using_debug_key", + "dr_inject_wait_for_child", + "dr_invoke_syscall_as_app", "dr_is_wow64", - "dr_create_client_thread", + "dr_lookup_module", + "dr_lookup_module_by_name", + "dr_module_contains_addr", + "dr_module_import_iterator_hasnext", + "dr_module_import_iterator_next", + "dr_module_import_iterator_start", + "dr_module_import_iterator_stop", + "dr_module_iterator_hasnext", + "dr_module_iterator_next", + "dr_module_iterator_start", + "dr_module_iterator_stop", + "dr_module_preferred_name", + "dr_module_set_should_instrument", + "dr_module_should_instrument", + "dr_nudge_pid", + "dr_num_registered_clients", + "dr_process_is_registered", + "dr_raw_brk", + "dr_raw_mremap", + "dr_register_client", + "dr_register_client_ex", + "dr_register_inject_paths", + "dr_register_kernel_xfer_event", + "dr_register_process", + "dr_set_isa_mode", + "dr_set_vector_length", + "dr_smp_exit", + "dr_symbol_export_iterator_hasnext", + "dr_symbol_export_iterator_next", + "dr_symbol_export_iterator_start", + "dr_symbol_export_iterator_stop", + "dr_symbol_import_iterator_hasnext", + "dr_symbol_import_iterator_next", + "dr_symbol_import_iterator_start", + "dr_symbol_import_iterator_stop", "dr_syscall_get_param", - "instr_branch_targets_prefix", - "INSTR_CREATE_nop2byte_reg", - "dr_get_stdin_file", - "dr_add_prefixes_to_basic_blocks", + "dr_syscall_get_result", + "dr_syscall_get_result_ex", + "dr_syscall_invoke_another", + "dr_syscall_set_param", + "dr_syscall_set_result", + "dr_syscall_set_result_ex", + "dr_syscall_set_sysnum", + "dr_unregister_client", + "dr_unregister_kernel_xfer_event", + "dr_unregister_process", + "drfront_access", + "drfront_appdata_logdir", + "drfront_bufprint", + "drfront_char_to_tchar", + "drfront_cleanup_args", + "drfront_convert_args", + "drfront_create_dir", + "drfront_dir_exists", + "drfront_dir_try_writable", + "drfront_fetch_module_symbols", + "drfront_get_absolute_path", + "drfront_get_app_full_path", + "drfront_get_env_var", + "drfront_is_64bit_app", + "drfront_is_graphical_app", + "drfront_remove_dir", + "drfront_searchenv", + "drfront_set_client_symbol_search_path", + "drfront_set_symbol_search_path", + "drfront_set_verbose", + "drfront_string_replace_character", + "drfront_string_replace_character_wide", + "drfront_sym_exit", + "drfront_sym_init", + "drfront_tchar_to_char", + "drfront_tchar_to_char_size_needed", + "get_register_name", + "instr_allocate_raw_bits", "instr_branch_set_prefix_target", + "instr_branch_targets_prefix", + "instr_build", + "instr_build_bits", + "instr_clear_label_callback", + "instr_clone", + "instr_compute_address", + "instr_compute_address_ex", + "instr_compute_address_ex_pos", + "instr_convert_short_meta_jmp_to_long", + "instr_convert_to_isa_regdeps", + "instr_create", + "instr_create_0dst_0src", + "instr_create_0dst_1src", + "instr_create_0dst_2src", + "instr_create_0dst_3src", + "instr_create_0dst_4src", + "instr_create_1dst_0src", + "instr_create_1dst_1src", + "instr_create_1dst_2src", + "instr_create_1dst_3src", + "instr_create_1dst_4src", + "instr_create_1dst_5src", + "instr_create_1dst_6src", + "instr_create_2dst_0src", + "instr_create_2dst_1src", + "instr_create_2dst_2src", + "instr_create_2dst_3src", + "instr_create_2dst_4src", + "instr_create_2dst_5src", + "instr_create_3dst_0src", + "instr_create_3dst_1src", + "instr_create_3dst_2src", + "instr_create_3dst_3src", + "instr_create_3dst_4src", + "instr_create_3dst_5src", + "instr_create_3dst_6src", + "instr_create_4dst_1src", + "instr_create_4dst_2src", + "instr_create_4dst_3src", + "instr_create_4dst_4src", + "instr_create_4dst_5src", + "instr_create_4dst_6src", + "instr_create_4dst_7src", + "instr_create_5dst_3src", + "instr_create_5dst_4src", + "instr_create_5dst_5src", + "instr_create_5dst_8src", + "instr_create_Ndst_Msrc_vardst", + "instr_create_Ndst_Msrc_varsrc", + "instr_destroy", + "instr_disassemble", + "instr_disassemble_to_buffer", + "instr_encode", + "instr_encode_to_copy", + "instr_exit_stub_code", + "instr_free", + "instr_free_raw_bits", + "instr_from_noalloc", + "instr_get_app_pc", + "instr_get_arith_flags", + "instr_get_branch_target_pc", + "instr_get_category", + "instr_get_category_name", + "instr_get_dst", + "instr_get_eflags", + "instr_get_interrupt_number", + "instr_get_isa_mode", + "instr_get_label_data_area", + "instr_get_next", + "instr_get_next_app", + "instr_get_note", + "instr_get_offset", + "instr_get_opcode", + "instr_get_opcode_eflags", + "instr_get_operation_size", + "instr_get_predicate", + "instr_get_prefix_flag", + "instr_get_prefixes", + "instr_get_prev", + "instr_get_prev_app", + "instr_get_raw_bits", + "instr_get_raw_byte", + "instr_get_raw_word", + "instr_get_rel_addr_dst_idx", + "instr_get_rel_addr_src_idx", + "instr_get_rel_addr_target", + "instr_get_rel_data_or_instr_target", + "instr_get_src", + "instr_get_target", + "instr_has_allocated_bits", + "instr_has_encoding_hint", + "instr_has_rel_addr_reference", + "instr_init", + "instr_is_app", + "instr_is_call", + "instr_is_cbr", + "instr_is_cti", + "instr_is_encoding_possible", + "instr_is_exit_cti", + "instr_is_label", + "instr_is_mbr", + "instr_is_meta", + "instr_is_meta_may_fault", + "instr_is_opnd_store_source", + "instr_is_predicated", + "instr_is_reg_spill_or_restore", + "instr_is_ubr", + "instr_is_xrstor", + "instr_is_xsave", + "instr_length", + "instr_make_persistent", + "instr_mem_usage", + "instr_memory_reference_size", + "instr_needs_encoding", + "instr_noalloc_init", + "instr_num_dsts", + "instr_num_memory_read_access", + "instr_num_memory_write_access", + "instr_num_srcs", + "instr_ok_to_emit", + "instr_ok_to_mangle", + "instr_opcode_valid", + "instr_operands_valid", + "instr_raw_bits_valid", + "instr_reads_from_exact_reg", + "instr_reads_from_reg", + "instr_reads_memory", + "instr_reg_in_dst", + "instr_reg_in_src", + "instr_remove_dsts", + "instr_remove_srcs", + "instr_replace_reg_resize", + "instr_replace_src_opnd", + "instr_reset", + "instr_reuse", + "instr_same", + "instr_set_app", + "instr_set_branch_target_pc", + "instr_set_category", + "instr_set_dst", + "instr_set_encoding_hint", "instr_set_exit_stub_code", + "instr_set_label_callback", + "instr_set_meta", + "instr_set_meta_may_fault", + "instr_set_meta_no_translation", + "instr_set_next", + "instr_set_note", + "instr_set_num_opnds", + "instr_set_ok_to_emit", + "instr_set_ok_to_mangle", + "instr_set_opcode", + "instr_set_operands_valid", + "instr_set_operation_size", + "instr_set_predicate", + "instr_set_prefix_flag", + "instr_set_prefixes", + "instr_set_prev", + "instr_set_raw_bits", + "instr_set_raw_bits_valid", + "instr_set_raw_byte", + "instr_set_raw_bytes", + "instr_set_raw_word", + "instr_set_src", + "instr_set_target", + "instr_set_translation", + "instr_shrink_to_16_bits", + "instr_shrink_to_32_bits", + "instr_uses_fp_reg", + "instr_uses_reg", + "instr_valid", + "instr_writes_memory", + "instr_writes_to_exact_reg", + "instr_writes_to_reg", + "instr_zeroes_ymmh", + "instr_zeroes_zmmh", + "instrlist_disassemble", + "opnd_add_flags", + "opnd_compute_address", + "opnd_create_abs_addr", + "opnd_create_base_disp", + "opnd_create_base_disp_ex", + "opnd_create_far_abs_addr", + "opnd_create_far_base_disp", + "opnd_create_far_base_disp_ex", + "opnd_create_far_instr", + "opnd_create_far_pc", + "opnd_create_far_rel_addr", + "opnd_create_immed_double", + "opnd_create_immed_float", + "opnd_create_immed_int", + "opnd_create_immed_int64", + "opnd_create_immed_uint", + "opnd_create_increment_reg", + "opnd_create_instr", + "opnd_create_instr_ex", + "opnd_create_mem_instr", + "opnd_create_null", + "opnd_create_pc", + "opnd_create_reg", + "opnd_create_reg_element_vector", + "opnd_create_reg_ex", + "opnd_create_reg_partial", + "opnd_create_rel_addr", + "opnd_defines_use", + "opnd_disassemble", + "opnd_disassemble_to_buffer", + "opnd_get_addr", + "opnd_get_base", + "opnd_get_disp", + "opnd_get_flags", + "opnd_get_immed_double", "opnd_get_immed_float", - "dr_client_thread_set_suspendable", - "dr_syscall_invoke_another", - "dr_get_stdout_file", - "dr_syscall_set_sysnum", - "dr_syscall_set_result", - "dr_syscall_set_param", - "dr_get_stderr_file", + "opnd_get_immed_int", + "opnd_get_immed_int64", + "opnd_get_index", + "opnd_get_instr", + "opnd_get_mem_instr_disp", + "opnd_get_pc", + "opnd_get_reg", + "opnd_get_reg_used", + "opnd_get_scale", + "opnd_get_segment", + "opnd_get_segment_selector", + "opnd_get_shift", + "opnd_get_size", + "opnd_get_vector_element_size", + "opnd_inc_reg", + "opnd_invert_immed_int", + "opnd_is_abs_addr", + "opnd_is_base_disp", + "opnd_is_disp_encode_zero", + "opnd_is_disp_force_full", + "opnd_is_disp_short_addr", + "opnd_is_element_vector_reg", + "opnd_is_far_abs_addr", + "opnd_is_far_base_disp", + "opnd_is_far_instr", + "opnd_is_far_memory_reference", + "opnd_is_far_pc", + "opnd_is_far_rel_addr", + "opnd_is_governing", + "opnd_is_immed", + "opnd_is_immed_float", + "opnd_is_immed_int", + "opnd_is_immed_int64", + "opnd_is_instr", + "opnd_is_mem_instr", + "opnd_is_memory_reference", + "opnd_is_near_abs_addr", + "opnd_is_near_base_disp", + "opnd_is_near_instr", + "opnd_is_near_memory_reference", + "opnd_is_near_pc", + "opnd_is_near_rel_addr", + "opnd_is_null", + "opnd_is_pc", + "opnd_is_predicate_merge", + "opnd_is_predicate_reg", + "opnd_is_predicate_zero", + "opnd_is_reg", + "opnd_is_reg_32bit", + "opnd_is_reg_64bit", + "opnd_is_reg_partial", + "opnd_is_reg_pointer_sized", + "opnd_is_rel_addr", + "opnd_is_vector_base_disp", + "opnd_is_vsib", + "opnd_num_regs_used", + "opnd_replace_reg", + "opnd_replace_reg_resize", + "opnd_same", + "opnd_same_address", + "opnd_set_disp", + "opnd_set_disp_ex", + "opnd_set_flags", + "opnd_set_size", + "opnd_share_reg", + "opnd_shrink_to_16_bits", + "opnd_shrink_to_32_bits", + "opnd_size_from_bytes", + "opnd_size_in_bits", + "opnd_size_in_bytes", + "opnd_uses_reg", + "proc_bump_to_end_of_cache_line", + "proc_get_L1_dcache_size", + "proc_get_L1_icache_size", + "proc_get_L2_cache_size", + "proc_get_all_feature_bits", + "proc_get_brand_string", + "proc_get_cache_line_size", + "proc_get_cache_size_str", + "proc_get_containing_page", + "proc_get_family", + "proc_get_model", + "proc_get_stepping", + "proc_get_type", + "proc_get_vendor", + "proc_is_cache_aligned", + "proc_set_vendor", + "reg_32_to_16", + "reg_32_to_64", + "reg_32_to_8", + "reg_32_to_opsz", + "reg_64_to_32", + "reg_get_bits", + "reg_get_size", + "reg_get_value", + "reg_get_value_ex", + "reg_is_32bit", + "reg_is_64bit", + "reg_is_avx512", + "reg_is_avx512_extended", + "reg_is_extended", + "reg_is_pointer_sized", + "reg_is_stolen", + "reg_overlap", + "reg_parameter_num", + "reg_resize_to_opsz", + "reg_set_value", + "reg_set_value_ex", + "reg_to_pointer_sized", } From d6ea492c2b073812efaddc9fbe54922e0020c781 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 30 Jun 2026 18:17:12 +0000 Subject: [PATCH 151/156] Reformat --- core/ir/x86/decode.c | 2 +- core/lib/dr_app.h | 3 ++- core/os_shared.h | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/core/ir/x86/decode.c b/core/ir/x86/decode.c index eff5bb13d..f9d8161ac 100644 --- a/core/ir/x86/decode.c +++ b/core/ir/x86/decode.c @@ -2894,7 +2894,7 @@ unit_check_decode_ff_opcode() instr_encode(dcontext, instr, pc); \ instr_reset(dcontext, instr); \ decode(dcontext, pc, instr); \ - /* XXX: use EXPECT */ \ + /* XXX: use EXPECT */ \ CLIENT_ASSERT(instr_get_opcode(instr) == OP_##opc, "unit test"); \ instr_destroy(dcontext, instr); diff --git a/core/lib/dr_app.h b/core/lib/dr_app.h index 4c8ae5c08..bf50a1658 100644 --- a/core/lib/dr_app.h +++ b/core/lib/dr_app.h @@ -47,7 +47,8 @@ # define DR_APP_API __declspec(dllimport) # endif #else /* UNIX */ -# if defined(DR_APP_EXPORTS) && defined(USE_VISIBILITY_ATTRIBUTES) && !defined(LINUX_KERNEL) +# if defined(DR_APP_EXPORTS) && defined(USE_VISIBILITY_ATTRIBUTES) && \ + !defined(LINUX_KERNEL) # define DR_APP_API __attribute__((visibility("default"))) # else # define DR_APP_API diff --git a/core/os_shared.h b/core/os_shared.h index c8b1047b6..48ade2ade 100644 --- a/core/os_shared.h +++ b/core/os_shared.h @@ -117,7 +117,8 @@ os_heap_exit(void); /* Called on each thread right before dispatching starts. This can be used to * warm the fragment cache. */ -void os_warm_fcache(dcontext_t* dcontext); +void +os_warm_fcache(dcontext_t *dcontext); #endif /* os provided heap routines */ From 6db62c80f431624be1cbb15bb0c7fb50fc1c8ab4 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 30 Jun 2026 18:29:15 +0000 Subject: [PATCH 152/156] Fix clang-format bug in CI --- core/arch/emit_utils_shared.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/core/arch/emit_utils_shared.c b/core/arch/emit_utils_shared.c index ae2d7ef05..66a601782 100644 --- a/core/arch/emit_utils_shared.c +++ b/core/arch/emit_utils_shared.c @@ -3295,12 +3295,15 @@ append_ibl_found(dcontext_t *dcontext, instrlist_t *ilist, ibl_code_t *ibl_code, } else { APP(ilist, SAVE_TO_TLS(dcontext, SCRATCH_REG2, INDIRECT_STUB_SPILL_SLOT)); #if defined(X86) && defined(X64) - if (x86_to_x64_ibl_opt) + if (x86_to_x64_ibl_opt) { APP(ilist, RESTORE_FROM_REG(dcontext, SCRATCH_REG2, REG_R9)); - else -#endif + } else { APP(ilist, RESTORE_FROM_TLS(dcontext, SCRATCH_REG2, MANGLE_XCX_SPILL_SLOT)); + } +#else + APP(ilist, RESTORE_FROM_TLS(dcontext, SCRATCH_REG2, MANGLE_XCX_SPILL_SLOT)); +#endif #if defined(AARCH64) || defined(RISCV64) ASSERT_NOT_IMPLEMENTED(false); /* TODO i#1569 i#3544 */ #else From cc06259a85979384dcd4a43941385fca2c0feebc Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Tue, 30 Jun 2026 19:00:45 +0000 Subject: [PATCH 153/156] Restrict ibl related procedures to kernel only --- core/arch/arch.c | 20 ++++++++++++++------ core/arch/arch.h | 12 +++++++++++- core/arch/arch_exports.h | 2 ++ core/arch/emit_utils_shared.c | 2 +- core/arch/x86/emit_utils.c | 4 ++++ 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/core/arch/arch.c b/core/arch/arch.c index e199fb7fc..acd971656 100644 --- a/core/arch/arch.c +++ b/core/arch/arch.c @@ -990,17 +990,22 @@ emit_ibl_routine_and_template(dcontext_t *dcontext, generated_code_t *code, byte ibl_code->thread_shared_routine = thread_shared; ibl_code->branch_type = branch_type; ibl_code->source_fragment_type = source_type; +#ifdef LINUX_KERNEL ibl_code->num_ibl_found_exits = 0; +#endif pc = emit_indirect_branch_lookup(dcontext, code, pc, fcache_return_pc, target_trace_table, inline_ibl_head, ibl_code); +#ifdef LINUX_KERNEL ibl_code->indirect_branch_lookup_routine_end = pc; +#endif if (inline_ibl_head) { /* create the inlined ibl template */ pc = check_size_and_cache_line(isa_mode, code, pc); pc = emit_inline_ibl_stub(dcontext, pc, ibl_code, target_trace_table); } +#ifdef LINUX_KERNEL pc = check_size_and_cache_line(isa_mode, code, pc); ibl_code->found_unlinked = pc; pc = emit_ibl_found_unlinked_code(dcontext, pc, fcache_return_pc, ibl_code, false, @@ -1017,6 +1022,7 @@ emit_ibl_routine_and_template(dcontext_t *dcontext, generated_code_t *code, byte ibl_code->found_unlinked_eflags_prefix = pc; pc = emit_ibl_found_unlinked_code(dcontext, pc, fcache_return_pc, ibl_code, true, true); +#endif ibl_code->far_ibl = pc; pc = emit_far_ibl( @@ -2665,22 +2671,23 @@ get_ibl_routine_code(dcontext_t *dcontext, ibl_branch_type_t branch_type, : GENCODE_FROM_DCONTEXT)); } +#ifdef LINUX_KERNEL ibl_code_t * get_ibl_code_from_routine_pc(dcontext_t *dcontext, cache_pc pc) { ibl_source_fragment_type_t source_fragment_type; ibl_branch_type_t branch_type; -#if defined(X86) && defined(X64) +# if defined(X86) && defined(X64) gencode_mode_t mode; -#endif +# endif for (source_fragment_type = IBL_SOURCE_TYPE_START; source_fragment_type < IBL_SOURCE_TYPE_END; source_fragment_type++) { for (branch_type = IBL_BRANCH_TYPE_START; branch_type < IBL_BRANCH_TYPE_END; branch_type++) { -#if defined(X86) && defined(X64) +# if defined(X86) && defined(X64) for (mode = GENCODE_X64; mode <= GENCODE_X86_TO_X64; mode++) { -#endif +# endif ibl_code_t *code = get_ibl_routine_code_internal( dcontext, source_fragment_type, branch_type _IF_X86_64(mode)); if (code != NULL && code->initialized && @@ -2688,13 +2695,14 @@ get_ibl_code_from_routine_pc(dcontext_t *dcontext, cache_pc pc) pc < code->indirect_branch_lookup_routine_end) { return code; } -#if defined(X86) && defined(X64) +# if defined(X86) && defined(X64) } -#endif +# endif } } return NULL; } +#endif #ifdef WINDOWS /* XXX We support a private and shared fragments simultaneously targeting diff --git a/core/arch/arch.h b/core/arch/arch.h index a0cce0072..20417ea5b 100644 --- a/core/arch/arch.h +++ b/core/arch/arch.h @@ -834,8 +834,13 @@ typedef struct patch_entry_t { negative offsets are from end of instruction */ } patch_entry_t; -#define MAX_IBL_FOUND_EXITS 2 +#ifdef LINUX_KERNEL +# define MAX_IBL_FOUND_EXITS 2 +#else +# define MAX_IBL_FOUND_EXITS 0 +#endif +#ifdef LINUX_KERNEL typedef struct ibl_found_exit_t { byte *jmp_pc; int original_jmp_length; @@ -845,6 +850,7 @@ typedef struct ibl_found_exit_t { /* True iff this exit restores eflags. */ bool restored_eflags; } ibl_found_exit_t; +#endif enum { MAX_PATCH_ENTRIES = @@ -923,6 +929,7 @@ typedef struct ibl_code_t { far_ref_t far_jmp_unlinked_opnd; #endif byte *unlinked_ibl_entry; +#ifdef LINUX_KERNEL byte *found_unlinked; byte *found_unlinked_eflags; byte *found_unlinked_prefix; @@ -930,6 +937,7 @@ typedef struct ibl_code_t { int num_ibl_found_exits; ibl_found_exit_t ibl_found_exits[MAX_IBL_FOUND_EXITS]; byte *indirect_branch_lookup_routine_end; +#endif byte *target_delete_entry; uint ibl_routine_length; /* offsets into ibl routine */ @@ -1249,10 +1257,12 @@ byte * emit_indirect_branch_lookup(dcontext_t *dcontext, generated_code_t *code, byte *pc, byte *fcache_return_pc, bool target_trace_table, bool inline_ibl_head, ibl_code_t *ibl_code); +#ifdef LINUX_KERNEL byte * emit_ibl_found_unlinked_code(dcontext_t *dcontext, byte *pc, byte *fcache_return_pc, ibl_code_t *ibl_code, bool restore_eflags, bool include_prefix); +#endif void update_indirect_branch_lookup(dcontext_t *dcontext); bool diff --git a/core/arch/arch_exports.h b/core/arch/arch_exports.h index 1e5559fe1..fbaf0ff30 100644 --- a/core/arch/arch_exports.h +++ b/core/arch/arch_exports.h @@ -1239,12 +1239,14 @@ void link_indirect_exit(dcontext_t *dcontext, fragment_t *f, linkstub_t *l, bool hot_patch); void unlink_indirect_exit(dcontext_t *dcontext, fragment_t *f, linkstub_t *l); +#ifdef LINUX_KERNEL void unlink_ibl_routine(dcontext_t *dcontext, cache_pc interrupted_ibl_pc); void link_ibl_routine(dcontext_t *dcontext, cache_pc interrupted_ibl_pc); struct ibl_code_t * get_ibl_code_from_routine_pc(dcontext_t *dcontext, cache_pc pc); +#endif void insert_fragment_prefix(dcontext_t *dcontext, fragment_t *f); int diff --git a/core/arch/emit_utils_shared.c b/core/arch/emit_utils_shared.c index 66a601782..fe0b1bc9d 100644 --- a/core/arch/emit_utils_shared.c +++ b/core/arch/emit_utils_shared.c @@ -3315,7 +3315,7 @@ append_ibl_found(dcontext_t *dcontext, instrlist_t *ilist, ibl_code_t *ibl_code, } inst = final_jmp; -#ifdef X86 +#if defined(X86) && defined(LINUX_KERNEL) if (final_jmp != NULL) { ibl_found_exit_t *exit; ASSERT(ibl_code->num_ibl_found_exits < MAX_IBL_FOUND_EXITS); diff --git a/core/arch/x86/emit_utils.c b/core/arch/x86/emit_utils.c index c708f9512..8d4a33359 100644 --- a/core/arch/x86/emit_utils.c +++ b/core/arch/x86/emit_utils.c @@ -934,6 +934,7 @@ unlink_indirect_exit(dcontext_t *dcontext, fragment_t *f, linkstub_t *l) #endif } +#ifdef LINUX_KERNEL static byte * get_ibl_found_unlinked_target(ibl_code_t *ibl_code, ibl_found_exit_t *exit) { @@ -986,6 +987,7 @@ link_ibl_routine(dcontext_t *dcontext, cache_pc interrupted_ibl_pc) { ibl_linking_common(dcontext, interrupted_ibl_pc, true /* link */); } +#endif /******************************************************************************* * COARSE-GRAIN FRAGMENT SUPPORT @@ -3145,6 +3147,7 @@ emit_indirect_branch_lookup(dcontext_t *dcontext, generated_code_t *code, byte * return pc + ibl_code->ibl_routine_length; } +#ifdef LINUX_KERNEL byte * emit_ibl_found_unlinked_code(dcontext_t *dcontext, byte *pc, byte *fcache_return_pc, ibl_code_t *ibl_code, bool restore_eflags, @@ -3190,6 +3193,7 @@ emit_ibl_found_unlinked_code(dcontext_t *dcontext, byte *pc, byte *fcache_return instrlist_clear_and_destroy(dcontext, ilist); return pc; } +#endif void relink_special_ibl_xfer(dcontext_t *dcontext, int index, From 062b3e2a07d1247dad95ff1231468ca1e8e8451c Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 6 Jul 2026 22:17:55 +0000 Subject: [PATCH 154/156] Add missing .o files to drk Makefile --- core/kernel_linux/modules/Makefile | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/core/kernel_linux/modules/Makefile b/core/kernel_linux/modules/Makefile index e0bd6f23f..2f8360120 100644 --- a/core/kernel_linux/modules/Makefile +++ b/core/kernel_linux/modules/Makefile @@ -48,7 +48,21 @@ dynamorio-objs :=\ ../../utils.o\ ../../barrier.o\ ../../vmareas.o\ +../../translate.o\ +../../string.o\ +../../lib/module_api.o\ ../../arch/arch.o\ +../../arch/emit_utils_shared.o\ +../../arch/proc_shared.o\ +../../arch/mangle_shared.o\ +../../arch/clean_call_opt_shared.o\ +../../arch/x86/clean_call_opt.o\ +../../ir/decode_shared.o\ +../../ir/disassemble_shared.o\ +../../ir/encode_shared.o\ +../../ir/instr_shared.o\ +../../ir/ir_utils_shared.o\ +../../ir/opnd_shared.o\ ../../ir/x86/decode.o\ ../../ir/x86/decode_fast.o\ ../../ir/x86/decode_table.o\ @@ -56,6 +70,8 @@ dynamorio-objs :=\ ../../arch/x86/emit_utils.o\ ../../ir/x86/encode.o\ ../../ir/x86/instr.o\ +../../ir/x86/opnd.o\ +../../ir/x86/ir_utils.o\ ../../lib/instrument.o\ ../../arch/interp.o\ ../../arch/loadtoconst.o\ From 28cee996b0e1369f492543d2686c42772c512502 Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 6 Jul 2026 22:30:05 +0000 Subject: [PATCH 155/156] Exclude irrelevant code from kernel build --- core/arch/mangle_shared.c | 20 +++++++++++--------- core/ir/opnd_shared.c | 6 ++++-- core/translate.c | 10 +++++----- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/core/arch/mangle_shared.c b/core/arch/mangle_shared.c index e10731482..6a635fd6e 100644 --- a/core/arch/mangle_shared.c +++ b/core/arch/mangle_shared.c @@ -935,7 +935,7 @@ get_call_return_address(dcontext_t *dcontext, instrlist_t *ilist, instr_t *instr return retaddr; } -#ifdef UNIX +#if defined(UNIX) && !defined(LINUX_KERNEL) /* find the system call number in instrlist for an inlined system call * by simpling walking the ilist backward and finding "mov immed => %eax" * without checking cti or expanding instr @@ -960,7 +960,7 @@ static void mangle_syscall(dcontext_t *dcontext, instrlist_t *ilist, uint flags, instr_t *instr, instr_t *next_instr) { -#ifdef UNIX +#if defined(UNIX) && !defined(LINUX_KERNEL) if (get_syscall_method() != SYSCALL_METHOD_INT && get_syscall_method() != SYSCALL_METHOD_SYSCALL && get_syscall_method() != SYSCALL_METHOD_SYSENTER && @@ -1019,12 +1019,12 @@ mangle_syscall(dcontext_t *dcontext, instrlist_t *ilist, uint flags, instr_t *in instr_set_app(instr); instrlist_postinsert(ilist, instr, nop); } -#endif /* UNIX */ +#endif /* UNIX && !LINUX_KERNEL */ mangle_syscall_arch(dcontext, ilist, flags, instr, next_instr); } -#ifdef UNIX +#if defined(UNIX) && !defined(LINUX_KERNEL) /* If skip is false: * changes the jmp right before the next syscall (after pc) to target the * exit cti immediately following it; @@ -1136,9 +1136,9 @@ mangle_syscall_code(dcontext_t *dcontext, fragment_t *f, byte *pc, bool skip) instr_free(dcontext, &instr); return true; } -#endif /* UNIX */ +#endif /* UNIX && !LINUX_KERNEL */ -#ifdef LINUX +#if defined(LINUX) && !defined(LINUX_KERNEL) /*************************************************************************** * Rseq (restartable sequence) mangling. */ @@ -1826,7 +1826,7 @@ mangle_rseq_finalize(dcontext_t *dcontext, instrlist_t *ilist, fragment_t *f) /* We should have found at least one set of labels. */ ASSERT(label_sets_found > 0); } -#endif /* LINUX */ +#endif /* LINUX && !LINUX_KERNEL */ /* TOP-LEVEL MANGLE * This routine is responsible for mangling a fragment into the form @@ -1914,7 +1914,7 @@ d_r_mangle(dcontext_t *dcontext, instrlist_t *ilist, uint *flags DR_PARAM_INOUT, translate_x86_to_x64(dcontext, ilist, &instr); #endif -#ifdef LINUX +#if defined(LINUX) && !defined(LINUX_KERNEL) /* Mangle stores inside restartable sequences ("rseq"). We could avoid the * per-instr check if we disallowed rseq blocks in traces and prevented * fall-through in a bb, but that would lead to more problems than it would @@ -2211,6 +2211,7 @@ cti_is_normal_elision(instr_t *instr) * (although -1 is invalid), so be sure to test for -1 and not just <0 as a failure * code. */ +#ifndef LINUX_KERNEL int find_syscall_num(dcontext_t *dcontext, instrlist_t *ilist, instr_t *instr) { @@ -2330,6 +2331,7 @@ find_syscall_num(dcontext_t *dcontext, instrlist_t *ilist, instr_t *instr) IF_X64(ASSERT_TRUNCATE(int, int, syscall)); return (int)syscall; } +#endif /* !LINUX_KERNEL */ void mangle_finalize(dcontext_t *dcontext, instrlist_t *ilist, fragment_t *f) @@ -2339,7 +2341,7 @@ mangle_finalize(dcontext_t *dcontext, instrlist_t *ilist, fragment_t *f) finalize_selfmod_sandbox(dcontext, f); } #endif -#ifdef LINUX +#if defined(LINUX) && !defined(LINUX_KERNEL) if (TEST(INSTR_RSEQ_ENDPOINT, ilist->flags)) mangle_rseq_finalize(dcontext, ilist, f); #endif diff --git a/core/ir/opnd_shared.c b/core/ir/opnd_shared.c index bf8269490..785da7c37 100644 --- a/core/ir/opnd_shared.c +++ b/core/ir/opnd_shared.c @@ -532,6 +532,7 @@ opnd_get_immed_int64(opnd_t opnd) (uint64)(uint)opnd.value.immed_int_multi_part.low; } +#ifndef LINUX_KERNEL /* NOTE: requires caller to be under PRESERVE_FLOATING_POINT_STATE */ float opnd_get_immed_float(opnd_t opnd) @@ -544,7 +545,7 @@ opnd_get_immed_float(opnd_t opnd) return opnd.value.immed_float; } -#ifndef WINDOWS +# ifndef WINDOWS /* XXX i#4488: x87 floating point immediates should be double precision. * Type double currently not included for Windows because sizeof(opnd_t) does * not equal EXPECTED_SIZEOF_OPND, triggering the ASSERT in d_r_arch_init(). @@ -556,7 +557,8 @@ opnd_get_immed_double(opnd_t opnd) "opnd_get_immed_double called on non-immed-float"); return opnd.value.immed_double; } -#endif +# endif +#endif /* !LINUX_KERNEL */ /* address operands */ diff --git a/core/translate.c b/core/translate.c index 29b0b3309..3b97638ca 100644 --- a/core/translate.c +++ b/core/translate.c @@ -167,7 +167,7 @@ instr_is_seg_ref_load(dcontext_t *dcontext, instr_t *inst) static inline bool instr_is_rseq_mangling(dcontext_t *dcontext, instr_t *inst) { -# ifdef LINUX +#if defined(LINUX) && !defined(LINUX_KERNEL) /* This won't fault but we don't want it marked as unsupported. */ if (!instr_is_our_mangling(inst)) return false; @@ -214,7 +214,7 @@ instr_is_rseq_mangling(dcontext_t *dcontext, instr_t *inst) opnd_get_disp(instr_get_dst(inst, 0)) == rseq_get_tls_ptr_offset()) return true; # endif -# endif +# endif /* LINUX && !LINUX_KERNEL */ return false; } #endif /* UNIX */ @@ -768,7 +768,7 @@ translate_restore_clean_call(dcontext_t *tdcontext, translate_walk_t *walk) app_pc translate_restore_special_cases(dcontext_t *dcontext, app_pc pc) { -#ifdef LINUX +#if defined(LINUX) && !defined(LINUX_KERNEL) app_pc handler; if (rseq_get_region_info(pc, NULL, NULL, &handler, NULL, NULL)) { LOG(THREAD_GET, LOG_INTERP, 2, @@ -786,7 +786,7 @@ translate_restore_special_cases(dcontext_t *dcontext, app_pc pc) app_pc translate_last_direct_translation(dcontext_t *dcontext, app_pc pc) { -#ifdef LINUX +#if defined(LINUX) && !defined(LINUX_KERNEL) app_pc handler; if (dcontext->client_data->last_special_xl8 != NULL && rseq_get_region_info(dcontext->client_data->last_special_xl8, NULL, NULL, @@ -800,7 +800,7 @@ translate_last_direct_translation(dcontext_t *dcontext, app_pc pc) void translate_clear_last_direct_translation(dcontext_t *dcontext) { -#ifdef LINUX +#if defined(LINUX) && !defined(LINUX_KERNEL) dcontext->client_data->last_special_xl8 = NULL; #endif } From 159f4e4d72730d951a81926414a3b35aa480b47d Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Mon, 6 Jul 2026 22:48:09 +0000 Subject: [PATCH 156/156] Handle float/double disassembly in kernel build --- core/ir/disassemble_shared.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/core/ir/disassemble_shared.c b/core/ir/disassemble_shared.c index 7aee19dea..0ab38a81c 100644 --- a/core/ir/disassemble_shared.c +++ b/core/ir/disassemble_shared.c @@ -683,6 +683,7 @@ internal_opnd_disassemble(char *buf, size_t bufsz, size_t *sofar DR_PARAM_INOUT, } } break; case IMMED_FLOAT_kind: { +#ifndef LINUX_KERNEL /* Save floating state for float printing. */ PRESERVE_FLOATING_POINT_STATE({ uint top; @@ -692,6 +693,10 @@ internal_opnd_disassemble(char *buf, size_t bufsz, size_t *sofar DR_PARAM_INOUT, print_to_buffer(buf, bufsz, sofar, "%s%s%u.%.6u", immed_prefix(), sign, top, bottom); }); +#else + print_to_buffer(buf, bufsz, sofar, "%s0x%08x /* float */", immed_prefix(), + *(const uint *)(&opnd.value.immed_float)); +#endif break; } #ifndef WINDOWS @@ -700,6 +705,7 @@ internal_opnd_disassemble(char *buf, size_t bufsz, size_t *sofar DR_PARAM_INOUT, * not equal EXPECTED_SIZEOF_OPND, triggering the ASSERT in d_r_arch_init(). */ case IMMED_DOUBLE_kind: { +# ifndef LINUX_KERNEL PRESERVE_FLOATING_POINT_STATE({ uint top; uint bottom; @@ -708,6 +714,10 @@ internal_opnd_disassemble(char *buf, size_t bufsz, size_t *sofar DR_PARAM_INOUT, print_to_buffer(buf, bufsz, sofar, "%s%s%u.%.6u", immed_prefix(), sign, top, bottom); }); +# else + print_to_buffer(buf, bufsz, sofar, "%s0x" ZHEX64_FORMAT_STRING " /* double */", + immed_prefix(), *(const uint64 *)(&opnd.value.immed_double)); +# endif break; } #endif