native: implement a working hello world compilation for w64 (#12577)
							parent
							
								
									04b030b7ab
								
							
						
					
					
						commit
						89bab98833
					
				|  | @ -71,6 +71,23 @@ fn get_all_commands() []Command { | ||||||
| 			line: '$vexe run examples/v_script.vsh > /dev/null' | 			line: '$vexe run examples/v_script.vsh > /dev/null' | ||||||
| 			okmsg: 'V can run the .VSH script file examples/v_script.vsh' | 			okmsg: 'V can run the .VSH script file examples/v_script.vsh' | ||||||
| 		} | 		} | ||||||
|  | 		//
 | ||||||
|  | 		res << Command{ | ||||||
|  | 			line: '$vexe -os linux -b native -o hw.linux examples/hello_world.v' | ||||||
|  | 			okmsg: 'V compiles hello_world.v on the native backend for linux' | ||||||
|  | 			rmfile: 'hw.linux' | ||||||
|  | 		} | ||||||
|  | 		res << Command{ | ||||||
|  | 			line: '$vexe -os macos -b native -o hw.macos examples/hello_world.v' | ||||||
|  | 			okmsg: 'V compiles hello_world.v on the native backend for macos' | ||||||
|  | 			rmfile: 'hw.macos' | ||||||
|  | 		} | ||||||
|  | 		res << Command{ | ||||||
|  | 			line: '$vexe -os windows -b native -o hw.exe examples/hello_world.v' | ||||||
|  | 			okmsg: 'V compiles hello_world.v on the native backend for windows' | ||||||
|  | 			rmfile: 'hw.exe' | ||||||
|  | 		} | ||||||
|  | 		//
 | ||||||
| 		res << Command{ | 		res << Command{ | ||||||
| 			line: '$vexe -b js -o hw.js examples/hello_world.v' | 			line: '$vexe -b js -o hw.js examples/hello_world.v' | ||||||
| 			okmsg: 'V compiles hello_world.v on the JS backend' | 			okmsg: 'V compiles hello_world.v on the JS backend' | ||||||
|  |  | ||||||
|  | @ -204,6 +204,14 @@ fn (mut g Gen) mov64(reg Register, val i64) { | ||||||
| 			g.write8(0xc7) | 			g.write8(0xc7) | ||||||
| 			g.write8(0xc1) | 			g.write8(0xc1) | ||||||
| 		} | 		} | ||||||
|  | 		.rdx { | ||||||
|  | 			g.write8(0x48) | ||||||
|  | 			g.write8(0xc7) | ||||||
|  | 			g.write8(0xc2) | ||||||
|  | 			g.write32(i32(int(val))) | ||||||
|  | 			g.println('mov32 $reg, $val') | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
| 		.rbx { | 		.rbx { | ||||||
| 			g.write8(0x48) | 			g.write8(0x48) | ||||||
| 			g.write8(0xc7) | 			g.write8(0xc7) | ||||||
|  | @ -427,7 +435,8 @@ pub fn (mut g Gen) allocate_string(s string, opsize int) int { | ||||||
| 	g.strings << s | 	g.strings << s | ||||||
| 	str_pos := g.buf.len + opsize | 	str_pos := g.buf.len + opsize | ||||||
| 	g.str_pos << str_pos | 	g.str_pos << str_pos | ||||||
| 	return 0 | 	g.strs << String{s, str_pos} | ||||||
|  | 	return str_pos | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn (mut g Gen) cld_repne_scasb() { | pub fn (mut g Gen) cld_repne_scasb() { | ||||||
|  | @ -484,7 +493,45 @@ pub fn (mut g Gen) gen_print_reg(r Register, n int, fd int) { | ||||||
| 	g.syscall() | 	g.syscall() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | pub fn (mut g Gen) apicall(s string) { | ||||||
|  | 	if g.pref.os != .windows { | ||||||
|  | 		g.n_error('apicalls are only for windows') | ||||||
|  | 	} | ||||||
|  | 	g.write8(0xff) | ||||||
|  | 	g.write8(0x15) | ||||||
|  | 	delta := match s { | ||||||
|  | 		'WriteFile' { | ||||||
|  | 			-(0xbcc + g.buf.len) | ||||||
|  | 		} | ||||||
|  | 		'GetStdHandle' { | ||||||
|  | 			-(0xbcc + g.buf.len + 8) | ||||||
|  | 		} | ||||||
|  | 		'ExitProcess' { | ||||||
|  | 			-(0xbcc + g.buf.len + 16) | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			0 | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	g.write32(delta) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| pub fn (mut g Gen) gen_print(s string, fd int) { | pub fn (mut g Gen) gen_print(s string, fd int) { | ||||||
|  | 	if g.pref.os == .windows { | ||||||
|  | 		g.sub(.rsp, 0x38) | ||||||
|  | 		g.mov(.rcx, -11) | ||||||
|  | 		g.apicall('GetStdHandle') | ||||||
|  | 		g.mov_reg(.rcx, .rax) | ||||||
|  | 		// g.mov64(.rdx, g.allocate_string(s, 3))
 | ||||||
|  | 		g.lea(.rdx, g.allocate_string(s, 3)) | ||||||
|  | 		g.mov(.r8, s.len) // string length
 | ||||||
|  | 		g.write([byte(0x4c), 0x8d, 0x4c, 0x24, 0x20]) // lea r9, [rsp+0x20]
 | ||||||
|  | 		g.write([byte(0x48), 0xc7, 0x44, 0x24, 0x20]) | ||||||
|  | 		g.write32(0) // mov qword[rsp+0x20], 0
 | ||||||
|  | 		// g.mov(.r9, rsp+0x20)
 | ||||||
|  | 		g.apicall('WriteFile') | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
| 	//
 | 	//
 | ||||||
| 	// qq := s + '\n'
 | 	// qq := s + '\n'
 | ||||||
| 	//
 | 	//
 | ||||||
|  | @ -554,8 +601,21 @@ pub fn (mut g Gen) gen_amd64_exit(expr ast.Expr) { | ||||||
| 			g.n_error('native builtin exit expects a numeric argument') | 			g.n_error('native builtin exit expects a numeric argument') | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	g.mov(.eax, g.nsyscall_exit()) | 	if g.pref.os == .windows { | ||||||
| 	g.syscall() | 		g.mov_reg(.rcx, .rdi) | ||||||
|  | 		g.apicall('ExitProcess') | ||||||
|  | 	} else { | ||||||
|  | 		g.mov(.eax, g.nsyscall_exit()) | ||||||
|  | 		g.syscall() | ||||||
|  | 	} | ||||||
|  | 	g.trap() // should never be reached, just in case
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn (mut g Gen) lea(reg Register, val int) { | ||||||
|  | 	g.write8(0x48) | ||||||
|  | 	g.write8(0x8d) | ||||||
|  | 	g.write8(0x15) | ||||||
|  | 	g.write32(val) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn (mut g Gen) mov(reg Register, val int) { | fn (mut g Gen) mov(reg Register, val int) { | ||||||
|  | @ -569,10 +629,15 @@ fn (mut g Gen) mov(reg Register, val int) { | ||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
| 			.rcx { | 			.rcx { | ||||||
| 				g.write8(0x48) | 				if val == -1 { | ||||||
| 				g.write8(0xc7) | 					g.write8(0x48) | ||||||
| 				g.write8(0xc1) | 					g.write8(0xc7) | ||||||
| 				g.write32(-1) | 					g.write8(0xc1) | ||||||
|  | 					g.write32(-1) | ||||||
|  | 				} else { | ||||||
|  | 					g.write8(0xff) | ||||||
|  | 					g.write8(0xff) // mov rcx 0xffff5
 | ||||||
|  | 				} | ||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
| 			else { | 			else { | ||||||
|  | @ -629,7 +694,16 @@ fn (mut g Gen) mov(reg Register, val int) { | ||||||
| 				g.write8(0xbf) | 				g.write8(0xbf) | ||||||
| 			} | 			} | ||||||
| 			.rcx { | 			.rcx { | ||||||
|  | 				g.write8(0x48) | ||||||
| 				g.write8(0xc7) | 				g.write8(0xc7) | ||||||
|  | 				g.write8(0xc1) | ||||||
|  | 			} | ||||||
|  | 			.r8 { | ||||||
|  | 				g.write8(0x41) | ||||||
|  | 				g.write8(0xb8) | ||||||
|  | 			} | ||||||
|  | 			.r9 { | ||||||
|  | 				g.write8(0xb9) | ||||||
| 			} | 			} | ||||||
| 			.rdx, .edx { | 			.rdx, .edx { | ||||||
| 				g.write8(0xba) | 				g.write8(0xba) | ||||||
|  | @ -738,6 +812,14 @@ fn (mut g Gen) mov_reg(a Register, b Register) { | ||||||
| 		g.write8(0x48) | 		g.write8(0x48) | ||||||
| 		g.write8(0x89) | 		g.write8(0x89) | ||||||
| 		g.write8(0xf8) | 		g.write8(0xf8) | ||||||
|  | 	} else if a == .rcx && b == .rdi { | ||||||
|  | 		g.write8(0x48) | ||||||
|  | 		g.write8(0x89) | ||||||
|  | 		g.write8(0xf9) | ||||||
|  | 	} else if a == .rcx && b == .rax { | ||||||
|  | 		g.write8(0x48) | ||||||
|  | 		g.write8(0x89) | ||||||
|  | 		g.write8(0xc1) | ||||||
| 	} else if a == .rdi && b == .rsi { | 	} else if a == .rdi && b == .rsi { | ||||||
| 		g.write8(0x48) | 		g.write8(0x48) | ||||||
| 		g.write8(0x89) | 		g.write8(0x89) | ||||||
|  | @ -1076,7 +1158,11 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) { | ||||||
| 
 | 
 | ||||||
| fn (mut g Gen) trap() { | fn (mut g Gen) trap() { | ||||||
| 	// funnily works on x86 and arm64
 | 	// funnily works on x86 and arm64
 | ||||||
| 	g.write32(0xcccccccc) | 	if g.pref.arch == .arm64 { | ||||||
|  | 		g.write32(0xcccccccc) | ||||||
|  | 	} else { | ||||||
|  | 		g.write8(0xcc) | ||||||
|  | 	} | ||||||
| 	g.println('trap') | 	g.println('trap') | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -47,6 +47,12 @@ mut: | ||||||
| 	size_pos             []int | 	size_pos             []int | ||||||
| 	nlines               int | 	nlines               int | ||||||
| 	callpatches          []CallPatch | 	callpatches          []CallPatch | ||||||
|  | 	strs                 []String | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct String { | ||||||
|  | 	str string | ||||||
|  | 	pos int | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct CallPatch { | struct CallPatch { | ||||||
|  | @ -176,6 +182,12 @@ pub fn (g &Gen) pos() i64 { | ||||||
| 	return g.buf.len | 	return g.buf.len | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn (mut g Gen) write(bytes []byte) { | ||||||
|  | 	for _, b in bytes { | ||||||
|  | 		g.buf << b | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| fn (mut g Gen) write8(n int) { | fn (mut g Gen) write8(n int) { | ||||||
| 	// write 1 byte
 | 	// write 1 byte
 | ||||||
| 	g.buf << byte(n) | 	g.buf << byte(n) | ||||||
|  |  | ||||||
|  | @ -395,9 +395,14 @@ fn (mut g Gen) write_symbol(s Symbol) { | ||||||
| fn (mut g Gen) sym_string_table() int { | fn (mut g Gen) sym_string_table() int { | ||||||
| 	begin := g.buf.len | 	begin := g.buf.len | ||||||
| 	g.zeroes(1) | 	g.zeroes(1) | ||||||
| 	at := i64(0x100000000) |  | ||||||
| 	for i, s in g.strings { | 	for i, s in g.strings { | ||||||
| 		g.write64_at(at + g.buf.len, int(g.str_pos[i])) | 		pos := g.buf.len - int(g.str_pos[i]) | ||||||
|  | 		if g.pref.os == .windows { | ||||||
|  | 			g.write32_at(int(g.str_pos[i]), pos - 4) // 0x402028 + pos)
 | ||||||
|  | 		} else { | ||||||
|  | 			baddr := i64(0x100000000) | ||||||
|  | 			g.write64_at(g.buf.len + baddr, int(g.str_pos[i])) | ||||||
|  | 		} | ||||||
| 		g.write_string(s) | 		g.write_string(s) | ||||||
| 		g.write8(0) | 		g.write8(0) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -1,9 +1,16 @@ | ||||||
| module native | module native | ||||||
| 
 | 
 | ||||||
| enum PeCharacteristics { | enum PeCharacteristics { | ||||||
| 	executable_image = 0x102 | 	// 1: relocation info stripped
 | ||||||
|  | 	// 2: file is executable
 | ||||||
|  | 	// 4: line numbers stripped
 | ||||||
|  | 	// 8: local symbols stripped
 | ||||||
|  | 	// 20: app can handle > 2GB
 | ||||||
|  | 	executable_image = 0x2f | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | const image_base = i64(0x400000) | ||||||
|  | 
 | ||||||
| enum PeMachine { | enum PeMachine { | ||||||
| 	i386 = 0x14c | 	i386 = 0x14c | ||||||
| 	amd64 = 0x8664 | 	amd64 = 0x8664 | ||||||
|  | @ -18,14 +25,14 @@ enum PeHeader { | ||||||
| pub fn (mut g Gen) write_dos_header() { | pub fn (mut g Gen) write_dos_header() { | ||||||
| 	dos_header := [ | 	dos_header := [ | ||||||
| 		int(PeHeader.mz), | 		int(PeHeader.mz), | ||||||
| 		0x90, // usedbytesinthelastpage
 | 		0x80, // bytes on last page of file
 | ||||||
| 		3, // filesizeinpages
 | 		1, // pages in file
 | ||||||
| 		0, // numofrelocs
 | 		0, // relocations
 | ||||||
| 		2, // header size in paragraph
 | 		4, // header size in paragraph
 | ||||||
| 		0, // minimum extra paragraphs
 | 		0x10, // minimum extra paragraphs
 | ||||||
| 		-1, // maximum extra paragraphs
 | 		0xffff, // maximum extra paragraphs
 | ||||||
| 		0, // initial relative ss
 | 		0, // initial relative ss
 | ||||||
| 		0xb8, // initial SP
 | 		0x140, // initial SP
 | ||||||
| 		0, // checksum
 | 		0, // checksum
 | ||||||
| 		0, // IP
 | 		0, // IP
 | ||||||
| 		0, // IP relative CS
 | 		0, // IP relative CS
 | ||||||
|  | @ -47,14 +54,14 @@ pub fn (mut g Gen) write_dos_header() { | ||||||
| 		0, | 		0, | ||||||
| 		0, | 		0, | ||||||
| 		0, | 		0, | ||||||
| 		0xf8, | 		0x80, | ||||||
| 		0, // address of PE header
 | 		0, // address of PE header
 | ||||||
| 	] | 	] | ||||||
| 	for b in dos_header { | 	for b in dos_header { | ||||||
| 		g.write16(b) | 		g.write16(b) | ||||||
| 	} | 	} | ||||||
| 	if g.buf.len != 0x40 { | 	if g.buf.len != 0x40 { | ||||||
| 		// g.warning('Invalid dos header size')
 | 		g.n_error('Invalid dos header size') | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -65,9 +72,46 @@ pub fn (mut g Gen) write_dos_stub() { | ||||||
| 	g.write8(0xba) // richend
 | 	g.write8(0xba) // richend
 | ||||||
| 	g.write8(0x0e) // richend
 | 	g.write8(0x0e) // richend
 | ||||||
| 	// TODO: add a stub for DOS/16, we only run on amd64
 | 	// TODO: add a stub for DOS/16, we only run on amd64
 | ||||||
| 	for g.buf.len < 0xf8 { | 	pad_to(mut g.buf, 0x80) | ||||||
| 		g.write8(0) // entries
 | } | ||||||
| 	} | 
 | ||||||
|  | fn (mut g Gen) write_pe_sections() { | ||||||
|  | 	pad_to(mut g.buf, 0x180) | ||||||
|  | 	g.write64(0) | ||||||
|  | 	g.write_string_with_padding('.idata', 8) | ||||||
|  | 	g.write32(0x89) // 137
 | ||||||
|  | 	g.write16(0x1000) | ||||||
|  | 	g.write32(0x02000000) | ||||||
|  | 	g.write32(0x02000000) | ||||||
|  | 	g.zeroes(14) | ||||||
|  | 	g.write16(64) | ||||||
|  | 	g.write8(0) | ||||||
|  | 	g.write8(192) | ||||||
|  | 	g.write_string_with_padding('.text', 8) | ||||||
|  | 	g.write32(75) | ||||||
|  | 	g.write8(0) | ||||||
|  | 	g.write32(0x20) | ||||||
|  | 	g.write32(0x00002) | ||||||
|  | 	g.write32(4) | ||||||
|  | 	g.write32(0) | ||||||
|  | 	g.write32(0) | ||||||
|  | 	g.write32(0x20000000) // 0, 0, 0, 32,
 | ||||||
|  | 	g.write([byte(0), 0, 96]) | ||||||
|  | 	g.zeroes(52) | ||||||
|  | 	g.write([byte(72), 16, 0, 0]) | ||||||
|  | 	g.write([byte(40), 16, 0, 0]) | ||||||
|  | 	g.zeroes(20) | ||||||
|  | 	g.write([byte(96), 16, 0, 0]) | ||||||
|  | 	g.write32(0) | ||||||
|  | 	g.write([byte(110), 16, 0, 0]) | ||||||
|  | 	g.write32(0) | ||||||
|  | 	g.write([byte(125), 16, 0, 0]) | ||||||
|  | 	g.zeroes(12) | ||||||
|  | 	g.write_string_with_padding('KERNEL32.DLL', 13) | ||||||
|  | 	g.write_string_with_padding('USER32.DLL', 13) | ||||||
|  | 	g.write_string_with_padding('ExitProcess', 14) | ||||||
|  | 	g.write_string_with_padding('GetStdHandle', 15) | ||||||
|  | 	g.write_string_with_padding('WriteFile', 13) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn (mut g Gen) write_pe_header() { | pub fn (mut g Gen) write_pe_header() { | ||||||
|  | @ -75,7 +119,7 @@ pub fn (mut g Gen) write_pe_header() { | ||||||
| 		int(PeHeader.pe), | 		int(PeHeader.pe), | ||||||
| 		0, | 		0, | ||||||
| 		int(PeMachine.amd64), // machine
 | 		int(PeMachine.amd64), // machine
 | ||||||
| 		1, // number of sections
 | 		2, // number of sections
 | ||||||
| 		0, | 		0, | ||||||
| 		0, // timestamp
 | 		0, // timestamp
 | ||||||
| 		0, | 		0, | ||||||
|  | @ -83,55 +127,59 @@ pub fn (mut g Gen) write_pe_header() { | ||||||
| 		0, // number of symbols
 | 		0, // number of symbols
 | ||||||
| 		0, | 		0, | ||||||
| 		0xf0, // 40 // size of optional header
 | 		0xf0, // 40 // size of optional header
 | ||||||
| 		int(PeCharacteristics.executable_image), // c
 | 		int(PeCharacteristics.executable_image), | ||||||
| 		// 0 // optional header magic
 |  | ||||||
| 	] | 	] | ||||||
| 	for b in pe_header { | 	for b in pe_header { | ||||||
| 		g.write16(b) | 		g.write16(b) | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
| 	// optional here comes here
 | 	// optional here comes here
 | ||||||
| 	p_opthdr := g.buf.len // should be 0x110
 | 	p_opthdr := g.buf.len // should be 0x110
 | ||||||
| 	if p_opthdr != 0x110 { | 	if p_opthdr != 0x98 { | ||||||
| 		eprintln('Invalid optdr location') | 		eprintln('Invalid optdr location $p_opthdr != 0x98') | ||||||
| 	} | 	} | ||||||
| 	g.write16(0x20b) // magic (0x10b=pe32, 0x20b=pe64)
 | 	g.write16(0x20b) // magic (0x10b=pe32, 0x20b=pe32+)
 | ||||||
| 	g.write8(0xe) // major linker version
 | 	g.write8(0x1) // major linker version
 | ||||||
| 	g.write8(0x1d) // minor linker version
 | 	g.write8(0x49) // minor linker version
 | ||||||
| 	g.write32(0x10) // sizeofcode
 | 	g.write32(0x200) // sizeofcode
 | ||||||
| 	g.write32(0x10) // initial data size
 | 	g.write32(0x200) // initial data size
 | ||||||
| 	g.write32(0) // sizeof sizeof uninit data
 | 	g.write32(0) // sizeof uninit data
 | ||||||
| 
 | 
 | ||||||
| 	image_base := i64(0x140000000) | 	g.write32(0x2000) // paddr of map // aligned to 4 bytes // entrypoint
 | ||||||
| 	g.write32(0x1188) // paddr of map // aligned to 4 bytes // entrypoint
 | 	g.write32(0x2000) // base of code // aligned to 4 bytes
 | ||||||
| 	g.write32(0x1000) // base of code // aligned to 4 bytes
 | 	g.write64(native.image_base) // image base vaddr // va // aligned to 4 bytes
 | ||||||
| 	g.write64(image_base) // image base vaddr // va // aligned to 4 bytes
 |  | ||||||
| 	g.write32(0x1000) // SectionAlignment
 | 	g.write32(0x1000) // SectionAlignment
 | ||||||
| 	g.write32(0x200) // FileAlignment
 | 	g.write32(0x200) // FileAlignment
 | ||||||
| 	g.write16(6) // Major OS Version
 | 	g.write16(1) // Major OS Version
 | ||||||
| 	g.write16(0) // Minor OS Version
 | 	g.write16(0) // Minor OS Version
 | ||||||
| 	g.write16(0) // major image version
 | 	g.write16(0) // major image version
 | ||||||
| 	g.write16(0) // minor image version
 | 	g.write16(0) // minor image version
 | ||||||
| 	g.write16(6) // major subsystem version
 | 	g.write16(5) // major subsystem version
 | ||||||
| 	g.write16(0) // minor subsystem version
 | 	g.write16(0) // minor subsystem version
 | ||||||
| 
 | 
 | ||||||
| 	g.write32(0) // win32versionvalue
 | 	g.write32(0) // win32versionvalue
 | ||||||
| 	g.write32(0x1000) // hdrsize + codelen) // sizeofimage
 | 	g.write32(0x3000) // hdrsize + codelen) // sizeofimage
 | ||||||
| 	g.write32(0x180) // hdrsize) // sizeofheaders
 | 	g.write32(0x200) // hdrsize) // sizeofheaders
 | ||||||
| 
 | 
 | ||||||
| 	g.write32(0) // checksum
 | 	g.write32(0) // checksum
 | ||||||
| 	g.write16(3) // subsystem // subsystem
 | 	g.write16(3) // subsystem // subsystem
 | ||||||
| 	// g.write16(0x400) // dll characteristics
 | 	// g.write16(0x400) // dll characteristics
 | ||||||
|  | 	g.write16(0) | ||||||
|  | 	/* | ||||||
| 	g.write8(0x60) // dll characteristics
 | 	g.write8(0x60) // dll characteristics
 | ||||||
| 	g.write8(0x81) // dll characteristics
 | 	g.write8(0x81) // dll characteristics
 | ||||||
| 	g.write64(0x100000) // SizeOfStackReserve
 | 	*/ | ||||||
|  | 	g.write64(0x1000) // SizeOfStackReserve
 | ||||||
| 	g.write64(0x1000) // SizeOfStackCommit
 | 	g.write64(0x1000) // SizeOfStackCommit
 | ||||||
| 	g.write64(0x100000) // SizeOfHeapReserve
 | 	g.write64(0x10000) // SizeOfHeapReserve
 | ||||||
| 	g.write64(0x1000) // SizeOfHeapCommit
 | 	g.write64(0) // SizeOfHeapCommit
 | ||||||
| 	g.write32(0) // LoaderFlags
 | 	g.write32(0) // LoaderFlags
 | ||||||
| 	g.write32(1) // NumberOfRvaAndSizes
 | 	g.write32(0x10) // NumberOfRvaAndSizes
 | ||||||
| 
 | 
 | ||||||
| 	g.write32(0) | 	g.write32(0) | ||||||
| 	g.write32(0) | 	g.write32(0) | ||||||
|  | 	g.write32(0x1000) | ||||||
|  | 	g.write32(0x100) // size of code
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn (mut g Gen) write_pe_section() { | fn (mut g Gen) write_pe_section() { | ||||||
|  | @ -155,30 +203,35 @@ pub fn (mut g Gen) generate_pe_header() { | ||||||
| 	g.write_dos_header() | 	g.write_dos_header() | ||||||
| 	g.write_dos_stub() | 	g.write_dos_stub() | ||||||
| 	g.write_pe_header() | 	g.write_pe_header() | ||||||
|  | 	g.write_pe_sections() | ||||||
|  | 
 | ||||||
|  | 	pad_to(mut g.buf, 0x400) | ||||||
| 	g.code_start_pos = g.buf.len | 	g.code_start_pos = g.buf.len | ||||||
| 
 | 
 | ||||||
| 	g.call(0x18e) | 	g.call(0x18e) | ||||||
| 	g.ret() | 	g.ret() | ||||||
|  | 	g.main_fn_addr = g.buf.len | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn pad_to(mut buf []byte, len int) { | ||||||
|  | 	for buf.len < len { | ||||||
|  | 		buf << byte(0) | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn (mut g Gen) generate_pe_footer() { | pub fn (mut g Gen) generate_pe_footer() { | ||||||
| 	/* | 	g.sym_string_table() | ||||||
| 	// TODO: when proper code is generated, uncomment this
 | 	pad_to(mut g.buf, 0x600) | ||||||
| 	codesize := g.buf.len - g.code_start_pos |  | ||||||
| 	delta := int(g.code_start_pos) // header_size
 |  | ||||||
| 	// patch the size depending on the codesize
 |  | ||||||
| 	for o in g.size_pos { |  | ||||||
| 		n := g.read32_at(o) |  | ||||||
| 		g.write32_at(o, n + delta) |  | ||||||
| 	} |  | ||||||
| 	*/ |  | ||||||
| 	for g.buf.len < 0x200 { |  | ||||||
| 		g.write8(0) // entries
 |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	g.write_pe_section() |  | ||||||
| 	g.file_size_pos = g.buf.len | 	g.file_size_pos = g.buf.len | ||||||
| 	g.main_fn_addr = g.buf.len | 
 | ||||||
| 	g.code_start_pos = g.buf.len | 	// patch call main
 | ||||||
|  | 	if g.pref.arch == .arm64 { | ||||||
|  | 		bl_next := u32(0x94000001) | ||||||
|  | 		g.write32_at(g.code_start_pos, int(bl_next)) | ||||||
|  | 	} else { | ||||||
|  | 		// +1 is for "e8"
 | ||||||
|  | 		// -5 is for "e8 00 00 00 00"
 | ||||||
|  | 		g.write32_at(g.code_start_pos + 1, int(g.main_fn_addr - g.code_start_pos) - 5) | ||||||
|  | 	} | ||||||
| 	g.create_executable() | 	g.create_executable() | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue