Forked from jakubtomsu/win32_copy_dll_data_sections.odin
Created
May 14, 2025 14:54
-
-
Save nahuakang/47a016129ad6a37748f13146827f587b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Failed experiment for a hotreload system. Instead of passing a big global struct pointer, try copying DLL global data sections. | |
copy_dll_data_sections :: proc( | |
dst: windows.HMODULE, | |
src: windows.HMODULE, | |
) -> bool { | |
dst_header := get_dll_nt_header(dst) or_return | |
src_header := get_dll_nt_header(src) or_return | |
dst_sections := cast([^]windows_IMAGE_SECTION_HEADER)windows_image_first_section(dst_header) | |
src_sections := cast([^]windows_IMAGE_SECTION_HEADER)windows_image_first_section(src_header) | |
for dst_section_index in 0..<dst_header.FileHeader.NumberOfSections { | |
dst_section := dst_sections[dst_section_index] | |
dst_addr := rawptr(uintptr(dst) + uintptr(dst_section.VirtualAddress)) | |
fmt.printfln("[%i] %8s:\taddr: %8p, data_ptr: %8p, data_size: %8i bytes (%M)", | |
dst_section_index, | |
transmute(string)dst_section.Name[:], | |
dst_addr, | |
rawptr(uintptr(dst_section.PointerToRawData)), | |
dst_section.SizeOfRawData, | |
dst_section.SizeOfRawData, | |
) | |
name := transmute(string)dst_section.Name[:] | |
// Section name whitelist | |
// Can use `@(link_section=".hotrel")` | |
switch dst_section.Name { | |
case | |
// {'.', 'b', 's', 's', 0, 0, 0, 0}, | |
// {'.', 'd', 'a', 't', 'a', 0, 0, 0}: | |
{'.', 'h', 'o', 't', 'r', 'e', 'l', 0}: | |
for src_section_index in 0..<src_header.FileHeader.NumberOfSections { | |
src_section := src_sections[src_section_index] | |
if src_section.Name != dst_section.Name { | |
continue | |
} | |
// Found valid section, now make sure it's valid | |
// Note: the sizes can vary by few bytes due to alignment | |
size := min(src_section.Misc.VirtualSize, dst_section.Misc.VirtualSize) | |
fmt.println("Src size:", src_section.Misc.VirtualSize) | |
fmt.println("Dst size:", dst_section.Misc.VirtualSize) | |
// Arbitrary threshold | |
if abs(int(src_section.Misc.VirtualSize) - int(dst_section.Misc.VirtualSize)) > 64 { | |
fmt.printfln("Error: section {} size doesn't match", name) | |
return false | |
} | |
fmt.printfln("Copying data of size %i bytes (%M) to address %p", | |
size, size, | |
dst_addr, | |
) | |
// Note: assume the memory pages are accessible for a DLL like ours... | |
runtime.mem_copy_non_overlapping( | |
dst = dst_addr, | |
src = rawptr(uintptr(src) + uintptr(src_section.VirtualAddress)), | |
len = int(size), | |
) | |
break | |
} | |
} | |
} | |
return true | |
} | |
get_dll_nt_header :: proc(lib: windows.HMODULE) -> (^windows.IMAGE_NT_HEADERS64, bool) { | |
dos_header := cast(^windows.IMAGE_DOS_HEADER)lib | |
if dos_header.e_magic != windows_IMAGE_DOS_SIGNATURE { | |
fmt.println("Not a DOS Header") | |
return nil, false | |
} | |
nt_header := cast(^windows.IMAGE_NT_HEADERS64)(uintptr(lib) + uintptr(dos_header.e_lfanew)) | |
if nt_header.Signature != windows_IMAGE_NT_SIGNATURE { | |
fmt.println("No NT Signature") | |
return nil, false | |
} | |
return nt_header, true | |
} | |
// Win32 shit | |
windows_IMAGE_DOS_SIGNATURE :: 0x5A4D // MZ | |
windows_IMAGE_OS2_SIGNATURE :: 0x454E // NE | |
windows_IMAGE_OS2_SIGNATURE_LE :: 0x454C // LE | |
windows_IMAGE_VXD_SIGNATURE :: 0x454C // LE | |
windows_IMAGE_NT_SIGNATURE :: 0x00004550 // PE00 | |
windows_image_first_section :: proc(ntheader: ^windows.IMAGE_NT_HEADERS64) -> ^windows_IMAGE_SECTION_HEADER { | |
return cast(^windows_IMAGE_SECTION_HEADER)( | |
uintptr(ntheader) + | |
offset_of(windows.IMAGE_NT_HEADERS64, OptionalHeader) + | |
uintptr(ntheader.FileHeader.SizeOfOptionalHeader)) | |
} | |
windows_IMAGE_SIZEOF_SHORT_NAME :: 8 | |
windows_IMAGE_SECTION_HEADER :: struct { | |
Name: [windows_IMAGE_SIZEOF_SHORT_NAME]windows.BYTE, | |
Misc: struct #raw_union { | |
PhysicalAddress: windows.DWORD, | |
VirtualSize: windows.DWORD, | |
}, | |
VirtualAddress: windows.DWORD, | |
SizeOfRawData: windows.DWORD, | |
PointerToRawData: windows.DWORD, | |
PointerToRelocations: windows.DWORD, | |
PointerToLinenumbers: windows.DWORD, | |
NumberOfRelocations: windows.WORD, | |
NumberOfLinenumbers: windows.WORD, | |
Characteristics: windows.DWORD, | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment