Created
May 14, 2025 10:10
-
-
Save jakubtomsu/02eea899d35b9cb59ee15ad36c48eda2 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