Improved Windows DLL calls
This commit is contained in:
parent
fa1dce31f3
commit
ed6cee0acc
12 changed files with 124 additions and 68 deletions
|
@ -10,6 +10,7 @@ import (
|
|||
"git.akyoto.dev/cli/q/src/asm"
|
||||
"git.akyoto.dev/cli/q/src/config"
|
||||
"git.akyoto.dev/cli/q/src/core"
|
||||
"git.akyoto.dev/cli/q/src/dll"
|
||||
"git.akyoto.dev/cli/q/src/exe/elf"
|
||||
"git.akyoto.dev/cli/q/src/exe/macho"
|
||||
"git.akyoto.dev/cli/q/src/exe/pe"
|
||||
|
@ -27,7 +28,7 @@ type Result struct {
|
|||
}
|
||||
|
||||
// finalize generates the final machine code.
|
||||
func (r *Result) finalize() ([]byte, []byte) {
|
||||
func (r *Result) finalize() ([]byte, []byte, dll.List) {
|
||||
// This will be the entry point of the executable.
|
||||
// The only job of the entry function is to call `main` and exit cleanly.
|
||||
// The reason we call `main` instead of using `main` itself is to place
|
||||
|
@ -49,15 +50,22 @@ func (r *Result) finalize() ([]byte, []byte) {
|
|||
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[1], 0)
|
||||
final.Syscall()
|
||||
case "windows":
|
||||
final.RegisterNumber(asm.SUB, x64.RSP, 32+8)
|
||||
final.RegisterNumber(asm.MOVE, x64.RCX, 0)
|
||||
final.Label(asm.CALL_AT, "ExitProcess")
|
||||
final.RegisterNumber(asm.MOVE, windows.X64InputRegisters[0], 0)
|
||||
final.DLLCall("kernel32.ExitProcess")
|
||||
}
|
||||
|
||||
dlls := dll.List{}
|
||||
|
||||
// This will place the main function immediately after the entry point
|
||||
// and also add everything the main function calls recursively.
|
||||
r.eachFunction(r.Main, map[*core.Function]bool{}, func(f *core.Function) {
|
||||
final.Merge(f.Assembler)
|
||||
|
||||
for _, library := range f.DLLs {
|
||||
for _, fn := range library.Functions {
|
||||
dlls = dlls.Append(library.Name, fn)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
final.Label(asm.LABEL, "_crash")
|
||||
|
@ -72,13 +80,12 @@ func (r *Result) finalize() ([]byte, []byte) {
|
|||
final.RegisterNumber(asm.MOVE, x64.SyscallInputRegisters[1], 1)
|
||||
final.Syscall()
|
||||
case "windows":
|
||||
final.RegisterNumber(asm.SUB, x64.RSP, 32+8)
|
||||
final.RegisterNumber(asm.MOVE, windows.X64InputRegisters[0], 1)
|
||||
final.Label(asm.CALL_AT, "ExitProcess")
|
||||
final.Label(asm.DLLCALL, "kernel32.ExitProcess")
|
||||
}
|
||||
|
||||
code, data := final.Finalize(windows.DLLs)
|
||||
return code, data
|
||||
code, data := final.Finalize(dlls)
|
||||
return code, data, dlls
|
||||
}
|
||||
|
||||
// eachFunction recursively finds all the calls to external functions.
|
||||
|
@ -116,8 +123,8 @@ func (r *Result) PrintInstructions() {
|
|||
|
||||
// Write writes the executable to the given writer.
|
||||
func (r *Result) Write(writer io.Writer) error {
|
||||
code, data := r.finalize()
|
||||
return write(writer, code, data)
|
||||
code, data, dlls := r.finalize()
|
||||
return write(writer, code, data, dlls)
|
||||
}
|
||||
|
||||
// Write writes an executable file to disk.
|
||||
|
@ -145,7 +152,7 @@ func (r *Result) WriteFile(path string) error {
|
|||
}
|
||||
|
||||
// write writes an executable file to the given writer.
|
||||
func write(writer io.Writer, code []byte, data []byte) error {
|
||||
func write(writer io.Writer, code []byte, data []byte, dlls dll.List) error {
|
||||
buffer := bufio.NewWriter(writer)
|
||||
|
||||
switch config.TargetOS {
|
||||
|
@ -154,7 +161,7 @@ func write(writer io.Writer, code []byte, data []byte) error {
|
|||
case "mac":
|
||||
macho.Write(buffer, code, data)
|
||||
case "windows":
|
||||
pe.Write(buffer, code, data, windows.DLLs)
|
||||
pe.Write(buffer, code, data, dlls)
|
||||
default:
|
||||
return fmt.Errorf("unsupported platform '%s'", config.TargetOS)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue