From d95ae091e7270407468d65cc14329305d90f7442 Mon Sep 17 00:00:00 2001 From: Linehu Date: Tue, 6 Oct 2026 21:37:37 +0800 Subject: [PATCH] fix(dkm): support R_X86_64_PLT32 relocations in ELF loader (DKM-E37) Multi-TU drivers produce PLT32 for cross-object calls (lld keeps a relocation for potentially-interposable global symbols). ath9k.drv (ath9k.o + wpa2_crypto.o) has 22 such relocations, which tripped "DKM-E37 UNSUPPORTED RELOCATION" at boot. PLT32 has the same semantics as PC32 in a static relocatable (patch = S + A - P), and is a 4-byte write. Added the constant, the patch computation, and switched the write-width branch to "not R_X86_64_64 -> u32" so all 4-byte types are handled uniformly. Verified: all 28 .drv files now use only {R_X86_64_32S, R_X86_64_64, R_X86_64_PC32, R_X86_64_PLT32}. --- CODE/UTSM/dkm/boot_modules.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/CODE/UTSM/dkm/boot_modules.c b/CODE/UTSM/dkm/boot_modules.c index ada86ab..b0cc89a 100644 --- a/CODE/UTSM/dkm/boot_modules.c +++ b/CODE/UTSM/dkm/boot_modules.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -29,6 +29,10 @@ #define R_X86_64_32 10 #define R_X86_64_32S 11 #define R_X86_64_PC32 2 +/* PLT32:lld 对(可能被覆盖的)全局函数调用生成,静态可重定位场景下 + * 语义与 PC32 相同(patch = S + A - P)。多编译单元驱动(如 ath9k + + * wpa2_crypto)跨 TU 调用即为此类型。 */ +#define R_X86_64_PLT32 4 void *memset(void *dst, int value, usize len); void *memcpy(void *dst, const void *src, usize len); @@ -363,7 +367,7 @@ int dkm_load_elf_rel(const void *address, u64 size, const struct dkm_symbol_scan patch = S + A; } else if (reloc_type == R_X86_64_32 || reloc_type == R_X86_64_32S) { patch = (u64)((i64)(i32)(S + A)); - } else if (reloc_type == R_X86_64_PC32) { + } else if (reloc_type == R_X86_64_PC32 || reloc_type == R_X86_64_PLT32) { patch = (u64)((i64)(i32)(S + A - P)); } else { log_error("[DKM] unsupported relocation type"); @@ -376,7 +380,7 @@ int dkm_load_elf_rel(const void *address, u64 size, const struct dkm_symbol_scan /* Bounds check: use the actual write width, not always 8. */ u32 reloc_width = (reloc_type == R_X86_64_64) ? 8 : 4; if (rela->offset + reloc_width <= target->size) { - if (reloc_type == R_X86_64_32 || reloc_type == R_X86_64_32S || reloc_type == R_X86_64_PC32) { + if (reloc_type != R_X86_64_64) { *(u32 *)(target_base + rela->offset) = (u32)patch; } else { *(u64 *)(target_base + rela->offset) = patch;